Compare commits
4 Commits
BOBS_MPI_E
...
alecf_fast
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
772d95df80 | ||
|
|
c92789df10 | ||
|
|
147b80a705 | ||
|
|
0bd57c4468 |
298
mozilla/mailnews/base/src/nsMsgMailSession.cpp
Normal file
298
mozilla/mailnews/base/src/nsMsgMailSession.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
//#include "nsIMsgIdentity.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
//#include "nsIPop3IncomingServer.h"
|
||||
#include "nsMsgMailSession.h"
|
||||
#include "nsMsgLocalCID.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMsgFolderCache.h"
|
||||
#include "nsIFileLocator.h"
|
||||
#include "nsFileLocations.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgMailSession, nsCOMTypeInfo<nsIMsgMailSession>::GetIID());
|
||||
|
||||
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
||||
static NS_DEFINE_CID(kMsgFolderCacheCID, NS_MSGFOLDERCACHE_CID);
|
||||
static NS_DEFINE_IID(kIFileLocatorIID, NS_IFILELOCATOR_IID);
|
||||
static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID);
|
||||
|
||||
//static NS_DEFINE_CID(kMsgIdentityCID, NS_MSGIDENTITY_CID);
|
||||
//static NS_DEFINE_CID(kPop3IncomingServerCID, NS_POP3INCOMINGSERVER_CID);
|
||||
//static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
|
||||
|
||||
nsMsgMailSession::nsMsgMailSession():
|
||||
mRefCnt(0),
|
||||
m_accountManager(0),
|
||||
m_msgFolderCache(0)
|
||||
{
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
nsMsgMailSession::~nsMsgMailSession()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::Init()
|
||||
{
|
||||
nsresult rv = NS_NewISupportsArray(getter_AddRefs(mListeners));
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::Shutdown()
|
||||
{
|
||||
if(m_accountManager)
|
||||
{
|
||||
if (m_msgFolderCache)
|
||||
m_accountManager->WriteToFolderCache(m_msgFolderCache);
|
||||
m_accountManager->CloseCachedConnections();
|
||||
m_accountManager->UnloadAccounts();
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(m_accountManager);
|
||||
|
||||
NS_IF_RELEASE(m_msgFolderCache);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIMsgMailSession
|
||||
nsresult nsMsgMailSession::GetCurrentIdentity(nsIMsgIdentity ** aIdentity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = GetAccountManager(getter_AddRefs(accountManager));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccount> defaultAccount;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = defaultAccount->GetDefaultIdentity(aIdentity);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
NS_ADDREF(*aIdentity);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetCurrentServer(nsIMsgIncomingServer ** aServer)
|
||||
{
|
||||
nsresult rv=NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = GetAccountManager(getter_AddRefs(accountManager));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccount> defaultAccount;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//if successful aServer will be addref'd by GetIncomingServer
|
||||
rv = defaultAccount->GetIncomingServer(aServer);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetAccountManager(nsIMsgAccountManager* *aAM)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAM);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
accountManager->LoadAccounts();
|
||||
|
||||
*aAM = accountManager;
|
||||
NS_IF_ADDREF(*aAM);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetFolderCache(nsIMsgFolderCache* *aFolderCache)
|
||||
{
|
||||
if (!aFolderCache) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!m_msgFolderCache)
|
||||
{
|
||||
rv = nsComponentManager::CreateInstance(kMsgFolderCacheCID,
|
||||
NULL,
|
||||
nsCOMTypeInfo<nsIMsgFolderCache>::GetIID(),
|
||||
(void **)&m_msgFolderCache);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr <nsIFileSpec> cacheFile;
|
||||
NS_WITH_SERVICE(nsIFileLocator, locator, kFileLocatorCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = locator->GetFileLocation(nsSpecialFileSpec::App_MessengerFolderCache50, getter_AddRefs(cacheFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
m_msgFolderCache->Init(cacheFile);
|
||||
|
||||
}
|
||||
|
||||
*aFolderCache = m_msgFolderCache;
|
||||
NS_IF_ADDREF(*aFolderCache);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetTemporaryMsgStatusFeedback(nsIMsgStatusFeedback* *aMsgStatusFeedback)
|
||||
{
|
||||
if (!aMsgStatusFeedback) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aMsgStatusFeedback = m_temporaryMsgStatusFeedback;
|
||||
NS_IF_ADDREF(*aMsgStatusFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgMailSession::SetTemporaryMsgStatusFeedback(nsIMsgStatusFeedback* aMsgStatusFeedback)
|
||||
{
|
||||
m_temporaryMsgStatusFeedback = do_QueryInterface(aMsgStatusFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::AddFolderListener(nsIFolderListener * listener)
|
||||
{
|
||||
mListeners->AppendElement(listener);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::RemoveFolderListener(nsIFolderListener * listener)
|
||||
{
|
||||
mListeners->RemoveElement(listener);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgMailSession::NotifyFolderItemPropertyChanged(nsISupports *item,
|
||||
const char *property,
|
||||
const char* oldValue,
|
||||
const char* newValue)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemPropertyChanged(item, property, oldValue, newValue);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgMailSession::NotifyFolderItemPropertyFlagChanged(nsISupports *item,
|
||||
const char *property,
|
||||
PRUint32 oldValue,
|
||||
PRUint32 newValue)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemPropertyFlagChanged(item, property, oldValue, newValue);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderItemAdded(nsIFolder *folder, nsISupports *item)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemAdded(folder, item);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderItemDeleted(nsIFolder *folder, nsISupports *item)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemRemoved(folder, item);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderLoaded(nsIFolder *folder)
|
||||
{
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnFolderLoaded(folder);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
mozilla/mailnews/base/util/MANIFEST
Normal file
35
mozilla/mailnews/base/util/MANIFEST
Normal file
@@ -0,0 +1,35 @@
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist:mailnews directory
|
||||
#
|
||||
|
||||
nsMsgLineBuffer.h
|
||||
nsMsgGroupRecord.h
|
||||
nsUInt32Array.h
|
||||
nsMsgKeySet.h
|
||||
nsMsgFolder.h
|
||||
nsMsgDBFolder.h
|
||||
nsLocalFolderSummarySpec.h
|
||||
nsMsgIdentity.h
|
||||
nsMsgIncomingServer.h
|
||||
nsNewsSummarySpec.h
|
||||
nsMsgUtils.h
|
||||
nsMessage.h
|
||||
nsMsgProtocol.h
|
||||
nsMsgTxn.h
|
||||
nsMsgMailNewsUrl.h
|
||||
nsMsgI18N.h
|
||||
|
||||
75
mozilla/mailnews/base/util/Makefile.in
Normal file
75
mozilla/mailnews/base/util/Makefile.in
Normal file
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = msgbaseutil
|
||||
LIBRARY_NAME = msgbaseutil
|
||||
|
||||
CPPSRCS = \
|
||||
nsMsgGroupRecord.cpp \
|
||||
nsMsgLineBuffer.cpp \
|
||||
nsMsgFolder.cpp \
|
||||
nsMsgDBFolder.cpp \
|
||||
nsUInt32Array.cpp \
|
||||
nsMsgKeySet.cpp \
|
||||
nsLocalFolderSummarySpec.cpp \
|
||||
nsNewsSummarySpec.cpp \
|
||||
nsMsgIdentity.cpp \
|
||||
nsMsgIncomingServer.cpp \
|
||||
nsMsgUtils.cpp \
|
||||
nsMessage.cpp \
|
||||
nsMsgProtocol.cpp \
|
||||
nsMsgMailNewsUrl.cpp \
|
||||
nsMsgTxn.cpp \
|
||||
nsMsgI18N.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsMsgGroupRecord.h \
|
||||
nsMsgLineBuffer.h \
|
||||
nsUInt32Array.h \
|
||||
nsMsgKeySet.h \
|
||||
nsMsgFolder.h \
|
||||
nsMsgDBFolder.h \
|
||||
nsLocalFolderSummarySpec.h \
|
||||
nsNewsSummarySpec.h \
|
||||
nsMsgIdentity.h \
|
||||
nsMsgIncomingServer.h \
|
||||
nsMsgUtils.h \
|
||||
nsMessage.h \
|
||||
nsMsgProtocol.h \
|
||||
nsMsgMailNewsUrl.h \
|
||||
nsMsgTxn.h \
|
||||
nsMsgI18N.h \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
-L$(DIST)/bin \
|
||||
-L$(DIST)/lib \
|
||||
-lxpcom \
|
||||
-lrdfutil_s \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
BIN
mozilla/mailnews/base/util/macbuild/msgUtil.mcp
Normal file
BIN
mozilla/mailnews/base/util/macbuild/msgUtil.mcp
Normal file
Binary file not shown.
21
mozilla/mailnews/base/util/macbuild/msgUtilPrefix.h
Normal file
21
mozilla/mailnews/base/util/macbuild/msgUtilPrefix.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MacPrefix.h"
|
||||
21
mozilla/mailnews/base/util/macbuild/msgUtilPrefixDebug.h
Normal file
21
mozilla/mailnews/base/util/macbuild/msgUtilPrefixDebug.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MacPrefix_debug.h"
|
||||
87
mozilla/mailnews/base/util/makefile.win
Normal file
87
mozilla/mailnews/base/util/makefile.win
Normal file
@@ -0,0 +1,87 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE= msgbsutl
|
||||
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
################################################################################
|
||||
## exports
|
||||
|
||||
EXPORTS= \
|
||||
nsMsgLineBuffer.h \
|
||||
nsMsgGroupRecord.h \
|
||||
nsUInt32Array.h \
|
||||
nsMsgKeySet.h \
|
||||
nsMsgFolder.h \
|
||||
nsMsgDBFolder.h \
|
||||
nsLocalFolderSummarySpec.h \
|
||||
nsMsgIdentity.h \
|
||||
nsMsgIncomingServer.h \
|
||||
nsNewsSummarySpec.h \
|
||||
nsMsgUtils.h \
|
||||
nsMessage.h \
|
||||
nsMsgProtocol.h \
|
||||
nsMsgMailNewsUrl.h \
|
||||
nsMsgTxn.h \
|
||||
nsMsgI18N.h \
|
||||
$(NULL)
|
||||
|
||||
################################################################################
|
||||
## library
|
||||
|
||||
LIBNAME = .\$(OBJDIR)\msgbsutl
|
||||
DLL = $(LIBNAME).dll
|
||||
|
||||
DEFINES=-D_IMPL_NS_MSG_BASE
|
||||
|
||||
LCFLAGS = \
|
||||
$(LCFLAGS) \
|
||||
$(DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsMsgGroupRecord.obj \
|
||||
.\$(OBJDIR)\nsMsgLineBuffer.obj \
|
||||
.\$(OBJDIR)\nsUInt32Array.obj \
|
||||
.\$(OBJDIR)\nsMsgKeySet.obj \
|
||||
.\$(OBJDIR)\nsMsgFolder.obj \
|
||||
.\$(OBJDIR)\nsMsgDBFolder.obj \
|
||||
.\$(OBJDIR)\nsLocalFolderSummarySpec.obj \
|
||||
.\$(OBJDIR)\nsMsgIdentity.obj \
|
||||
.\$(OBJDIR)\nsMsgIncomingServer.obj \
|
||||
.\$(OBJDIR)\nsNewsSummarySpec.obj \
|
||||
.\$(OBJDIR)\nsMsgUtils.obj \
|
||||
.\$(OBJDIR)\nsMessage.obj \
|
||||
.\$(OBJDIR)\nsMsgProtocol.obj \
|
||||
.\$(OBJDIR)\nsMsgMailNewsUrl.obj \
|
||||
.\$(OBJDIR)\nsMsgTxn.obj \
|
||||
.\$(OBJDIR)\nsMsgI18N.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\rdfutil_s.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
libs:: $(DLL)
|
||||
$(MAKE_INSTALL) $(LIBNAME).$(DLL_SUFFIX) $(DIST)\bin
|
||||
$(MAKE_INSTALL) $(LIBNAME).$(LIB_SUFFIX) $(DIST)\lib
|
||||
76
mozilla/mailnews/base/util/nsLocalFolderSummarySpec.cpp
Normal file
76
mozilla/mailnews/base/util/nsLocalFolderSummarySpec.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsLocalFolderSummarySpec.h"
|
||||
#include "plstr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsLocalFolderSummarySpec);
|
||||
|
||||
nsLocalFolderSummarySpec::~nsLocalFolderSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsLocalFolderSummarySpec);
|
||||
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const char *folderPath, PRBool create)
|
||||
: nsFileSpec(folderPath, create)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const nsFileSpec& inFolderPath)
|
||||
: nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const nsFilePath &inFolderPath, PRBool create) : nsFileSpec(inFolderPath, create)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
void nsLocalFolderSummarySpec::SetFolderName(const char *folderPath)
|
||||
{
|
||||
*this = folderPath;
|
||||
}
|
||||
|
||||
void nsLocalFolderSummarySpec:: CreateSummaryFileName()
|
||||
{
|
||||
char *leafName = GetLeafName();
|
||||
|
||||
nsString fullLeafName(leafName);
|
||||
|
||||
// Append .msf (msg summary file) this is what windows will want.
|
||||
// Mac and Unix can decide for themselves.
|
||||
|
||||
fullLeafName += ".msf"; // message summary file
|
||||
char *cLeafName = fullLeafName.ToNewCString();
|
||||
SetLeafName(cLeafName);
|
||||
nsAllocator::Free(cLeafName);
|
||||
PL_strfree(leafName);
|
||||
}
|
||||
|
||||
46
mozilla/mailnews/base/util/nsLocalFolderSummarySpec.h
Normal file
46
mozilla/mailnews/base/util/nsLocalFolderSummarySpec.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsLocalFolderSummarySpec_H
|
||||
#define _nsLocalFolderSummarySpec_H
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsFileSpec.h"
|
||||
|
||||
// Class to name a summary file for a local mail folder,
|
||||
// given a full folder file spec. For windows, this just means tacking .msf on the end.
|
||||
// For Unix, it might mean something like putting a '.' on the front and .msgsummary on the end.
|
||||
// Note this class expects the invoking code to fully specify the folder path.
|
||||
// This class does NOT prepend the local folder directory, or put .sbd on the containing
|
||||
// directory names.
|
||||
class NS_MSG_BASE nsLocalFolderSummarySpec : public nsFileSpec
|
||||
{
|
||||
public:
|
||||
virtual ~nsLocalFolderSummarySpec();
|
||||
nsLocalFolderSummarySpec();
|
||||
nsLocalFolderSummarySpec(const char *folderPath, PRBool create = PR_FALSE);
|
||||
nsLocalFolderSummarySpec(const nsFileSpec& inFolderPath);
|
||||
nsLocalFolderSummarySpec(const nsFilePath &inFolderPath, PRBool create = PR_FALSE);
|
||||
void SetFolderName(const char *folderPath);
|
||||
|
||||
protected:
|
||||
void CreateSummaryFileName();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
509
mozilla/mailnews/base/util/nsMessage.cpp
Normal file
509
mozilla/mailnews/base/util/nsMessage.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "nsMessage.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
|
||||
|
||||
nsMessage::nsMessage(void)
|
||||
: nsRDFResource(), mFolder(nsnull)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsMessage::~nsMessage(void)
|
||||
{
|
||||
//Member variables are either nsCOMPtr's or ptrs we don't want to own.
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsMessage, nsRDFResource)
|
||||
NS_IMPL_RELEASE_INHERITED(nsMessage, nsRDFResource)
|
||||
|
||||
NS_IMETHODIMP nsMessage::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
||||
*aInstancePtr = nsnull;
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIMessage>::GetIID()) || aIID.Equals(nsCOMTypeInfo<nsIDBMessage>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIDBMessage*, this);
|
||||
}
|
||||
if(*aInstancePtr)
|
||||
{
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsRDFResource::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessage::Init(const char* aURI)
|
||||
{
|
||||
|
||||
return nsRDFResource::Init(aURI);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetProperty(const char *propertyName, nsString &resultProperty)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetProperty(propertyName, resultProperty);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetProperty(const char *propertyName, nsString &propertyStr)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetProperty(propertyName, propertyStr);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetUint32Property(const char *propertyName, PRUint32 *pResult)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetUint32Property(propertyName, pResult);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetUint32Property(const char *propertyName, PRUint32 propertyVal)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetUint32Property(propertyName, propertyVal);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetNumReferences(PRUint16 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetNumReferences(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetStringReference(PRInt32 refNum, nsCString &resultReference)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetStringReference(refNum, resultReference);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetDate(PRTime *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetDate(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetDate(PRTime date)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetDate(date);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageId(const char *messageId)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageId(messageId);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetReferences(const char *references)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetReferences(references);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetCCList(const char *ccList)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetCCList(ccList);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetRecipients(const char *recipients, PRBool recipientsIsNewsgroup)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetRecipients(recipients, recipientsIsNewsgroup);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetRecipientsArray(names, addresses, numAddresses);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetCCListArray(names, addresses, numAddresses);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetAuthor(const char *author)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetAuthor(author);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetSubject(const char *subject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetSubject(subject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetStatusOffset(PRUint32 statusOffset)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetStatusOffset(statusOffset);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetAuthor(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetAuthor(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetSubject(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetSubject(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetRecipients(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetRecipients(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetCCList(nsString *ccList)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetCCList(ccList);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageId(nsCString *resultMessageId)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageId(resultMessageId);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedAuthor(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedAuthor(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedSubject(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedSubject(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedRecipients(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedRecipients(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetAuthorCollationKey(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetAuthorCollationKey(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetSubjectCollationKey(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetSubjectCollationKey(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetRecipientsCollationKey(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetRecipientsCollationKey(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetFlags(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetFlags(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetFlags(PRUint32 flags)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetFlags(flags);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::OrFlags(PRUint32 flags, PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->OrFlags(flags, result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::AndFlags(PRUint32 flags, PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->AndFlags(flags, result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::MarkRead(PRBool bRead)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->MarkRead(bRead);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::MarkFlagged(PRBool bFlagged)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->MarkFlagged(bFlagged);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageKey(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageKey(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetThreadId(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetThreadId(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetThreadId(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetThreadId(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageKey(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageKey(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageSize(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageSize(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetLineCount(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetLineCount(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageSize(PRUint32 messageSize)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageSize(messageSize);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetLineCount(PRUint32 lineCount)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetLineCount(lineCount);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetPriority(nsMsgPriority priority)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetPriority(priority);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetPriority(const char *priority)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetPriority(priority);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetPriority(nsMsgPriority *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetPriority(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageOffset(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageOffset(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetStatusOffset(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetStatusOffset(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetCharSet(nsString *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetCharSet(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetThreadParent(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetThreadParent(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetThreadParent(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetThreadParent(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMsgFolder(nsIMsgFolder **folder)
|
||||
{
|
||||
if(!folder)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*folder = mFolder;
|
||||
if(mFolder)
|
||||
{
|
||||
NS_ADDREF(mFolder);
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMsgFolder(nsIMsgFolder *folder)
|
||||
{
|
||||
mFolder = folder;
|
||||
//We don't want to own folder, so don't AddRef
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMsgDBHdr(nsIMsgDBHdr *hdr)
|
||||
{
|
||||
mMsgHdr = dont_QueryInterface(hdr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMsgDBHdr(nsIMsgDBHdr **hdr)
|
||||
{
|
||||
*hdr = mMsgHdr;
|
||||
if(*hdr)
|
||||
{
|
||||
NS_ADDREF(*hdr);
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
113
mozilla/mailnews/base/util/nsMessage.h
Normal file
113
mozilla/mailnews/base/util/nsMessage.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Messenger folders.
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsMessage_h__
|
||||
#define nsMessage_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h" /* include the interface we are going to support */
|
||||
#include "nsRDFResource.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMessage: public nsRDFResource, public nsIDBMessage
|
||||
{
|
||||
public:
|
||||
nsMessage(void);
|
||||
virtual ~nsMessage(void);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIMESSAGE
|
||||
NS_DECL_NSIDBMESSAGE
|
||||
|
||||
NS_IMETHOD Init(const char *aURI);
|
||||
//nsIMsgHdr
|
||||
NS_IMETHOD GetProperty(const char *propertyName, nsString &resultProperty);
|
||||
NS_IMETHOD SetProperty(const char *propertyName, nsString &propertyStr);
|
||||
NS_IMETHOD GetUint32Property(const char *propertyName, PRUint32 *pResult);
|
||||
NS_IMETHOD SetUint32Property(const char *propertyName, PRUint32 propertyVal);
|
||||
NS_IMETHOD GetNumReferences(PRUint16 *result);
|
||||
NS_IMETHOD GetStringReference(PRInt32 refNum, nsCString &resultReference);
|
||||
NS_IMETHOD GetDate(PRTime *result);
|
||||
NS_IMETHOD SetDate(PRTime date);
|
||||
NS_IMETHOD SetMessageId(const char *messageId);
|
||||
NS_IMETHOD SetReferences(const char *references);
|
||||
NS_IMETHOD SetCCList(const char *ccList);
|
||||
NS_IMETHOD SetRecipients(const char *recipients, PRBool recipientsIsNewsgroup);
|
||||
NS_IMETHOD SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses);
|
||||
NS_IMETHOD SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses);
|
||||
NS_IMETHOD SetAuthor(const char *author);
|
||||
NS_IMETHOD SetSubject(const char *subject);
|
||||
NS_IMETHOD SetStatusOffset(PRUint32 statusOffset);
|
||||
|
||||
NS_IMETHOD GetAuthor(nsString *resultAuthor);
|
||||
NS_IMETHOD GetSubject(nsString *resultSubject);
|
||||
NS_IMETHOD GetRecipients(nsString *resultRecipients);
|
||||
NS_IMETHOD GetCCList(nsString *ccList);
|
||||
NS_IMETHOD GetMessageId(nsCString *resultMessageId);
|
||||
|
||||
NS_IMETHOD GetMime2DecodedAuthor(nsString *resultAuthor);
|
||||
NS_IMETHOD GetMime2DecodedSubject(nsString *resultSubject);
|
||||
NS_IMETHOD GetMime2DecodedRecipients(nsString *resultRecipients);
|
||||
|
||||
NS_IMETHOD GetAuthorCollationKey(nsString *resultAuthor);
|
||||
NS_IMETHOD GetSubjectCollationKey(nsString *resultSubject);
|
||||
NS_IMETHOD GetRecipientsCollationKey(nsString *resultRecipients);
|
||||
|
||||
// flag handling routines
|
||||
NS_IMETHOD GetFlags(PRUint32 *result);
|
||||
NS_IMETHOD SetFlags(PRUint32 flags);
|
||||
NS_IMETHOD OrFlags(PRUint32 flags, PRUint32 *result);
|
||||
NS_IMETHOD AndFlags(PRUint32 flags, PRUint32 *result);
|
||||
|
||||
// Mark message routines
|
||||
NS_IMETHOD MarkRead(PRBool bRead);
|
||||
NS_IMETHOD MarkFlagged(PRBool bFlagged);
|
||||
|
||||
NS_IMETHOD GetMessageKey(nsMsgKey *result);
|
||||
NS_IMETHOD GetThreadId(nsMsgKey *result);
|
||||
NS_IMETHOD SetThreadId(nsMsgKey inKey);
|
||||
NS_IMETHOD SetMessageKey(nsMsgKey inKey);
|
||||
NS_IMETHOD GetMessageSize(PRUint32 *result);
|
||||
NS_IMETHOD SetMessageSize(PRUint32 messageSize);
|
||||
NS_IMETHOD GetLineCount(PRUint32 *result);
|
||||
NS_IMETHOD SetLineCount(PRUint32 lineCount);
|
||||
NS_IMETHOD SetPriority(nsMsgPriority priority);
|
||||
NS_IMETHOD SetPriority(const char *priority);
|
||||
NS_IMETHOD GetMessageOffset(PRUint32 *result);
|
||||
NS_IMETHOD GetStatusOffset(PRUint32 *result);
|
||||
NS_IMETHOD GetCharSet(nsString *result);
|
||||
NS_IMETHOD GetPriority(nsMsgPriority *result);
|
||||
NS_IMETHOD GetThreadParent(nsMsgKey *result);
|
||||
NS_IMETHOD SetThreadParent(nsMsgKey inKey);
|
||||
|
||||
protected:
|
||||
nsIMsgFolder *mFolder;
|
||||
nsCOMPtr<nsIMsgDBHdr> mMsgHdr;
|
||||
|
||||
};
|
||||
|
||||
#endif //nsMessage_h__
|
||||
|
||||
530
mozilla/mailnews/base/util/nsMsgDBFolder.cpp
Normal file
530
mozilla/mailnews/base/util/nsMsgDBFolder.cpp
Normal file
@@ -0,0 +1,530 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsMsgDBFolder.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIMsgFolderCache.h"
|
||||
#include "nsIMsgFolderCacheElement.h"
|
||||
#include "nsIMsgMailSession.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
||||
NS_IMPL_RELEASE_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
||||
*aInstancePtr = nsnull;
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIDBChangeListener>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIDBChangeListener*, this);
|
||||
}
|
||||
else if (aIID.Equals(nsCOMTypeInfo<nsIUrlListener>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIUrlListener*, this);
|
||||
}
|
||||
|
||||
if(*aInstancePtr)
|
||||
{
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsRDFResource::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
nsMsgDBFolder::nsMsgDBFolder(void)
|
||||
: mCharset(""), mAddListener(PR_TRUE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsMsgDBFolder::~nsMsgDBFolder(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
{
|
||||
mDatabase->RemoveListener(this);
|
||||
mDatabase->Close(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::StartFolderLoading(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
mDatabase->RemoveListener(this);
|
||||
mAddListener = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::EndFolderLoading(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
mDatabase->AddListener(this);
|
||||
mAddListener = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetThreads(nsISimpleEnumerator** threadEnumerator)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return mDatabase->EnumerateThreads(threadEnumerator);
|
||||
else
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = mDatabase->GetThreadContainingMsgHdr(msgDBHdr, thread);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::HasMessage(nsIMessage *message, PRBool *hasMessage)
|
||||
{
|
||||
if(!hasMessage)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr, msgDBHdrForKey;
|
||||
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
||||
nsMsgKey key;
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = msgDBHdr->GetMessageKey(&key);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = mDatabase->ContainsKey(key, hasMessage);
|
||||
|
||||
}
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetCharset(PRUnichar * *aCharset)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if(!aCharset)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if(mCharset == "")
|
||||
{
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
|
||||
char *prefCharset = nsnull;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = prefs->CopyCharPref("intl.character_set_name", &prefCharset);
|
||||
}
|
||||
|
||||
nsString prefCharsetStr;
|
||||
if(prefCharset)
|
||||
{
|
||||
prefCharsetStr = prefCharset;
|
||||
PR_Free(prefCharset);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefCharsetStr = "us-ascii";
|
||||
}
|
||||
*aCharset = prefCharsetStr.ToNewUnicode();
|
||||
}
|
||||
else
|
||||
{
|
||||
*aCharset = mCharset.ToNewUnicode();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::SetCharset(const PRUnichar * aCharset)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
||||
nsCOMPtr<nsIMsgDatabase> db;
|
||||
rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsString charset(aCharset);
|
||||
rv = folderInfo->SetCharacterSet(&charset);
|
||||
db->Commit(nsMsgDBCommitType::kLargeCommit);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::ReadDBFolderInfo(PRBool force)
|
||||
{
|
||||
// Since it turns out to be pretty expensive to open and close
|
||||
// the DBs all the time, if we have to open it once, get everything
|
||||
// we might need while we're here
|
||||
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr <nsIMsgFolderCache> folderCache;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &result);
|
||||
if(NS_SUCCEEDED(result))
|
||||
{
|
||||
result = mailSession->GetFolderCache(getter_AddRefs(folderCache));
|
||||
if (NS_SUCCEEDED(result) && folderCache)
|
||||
{
|
||||
char *uri;
|
||||
|
||||
result = GetURI(&uri);
|
||||
if (NS_SUCCEEDED(result) && uri)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
||||
result = folderCache->GetCacheElement(uri, PR_FALSE, getter_AddRefs(cacheElement));
|
||||
if (NS_SUCCEEDED(result) && cacheElement)
|
||||
{
|
||||
result = ReadFromFolderCache(cacheElement);
|
||||
}
|
||||
PR_Free(uri);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// if (m_master->InitFolderFromCache (this))
|
||||
// return err;
|
||||
|
||||
if (force || !(mPrefFlags & MSG_FOLDER_PREF_CACHED))
|
||||
{
|
||||
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
||||
nsCOMPtr<nsIMsgDatabase> db;
|
||||
result = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
||||
if(NS_SUCCEEDED(result))
|
||||
{
|
||||
mIsCachable = PR_TRUE;
|
||||
if (folderInfo)
|
||||
{
|
||||
|
||||
folderInfo->GetFlags(&mPrefFlags);
|
||||
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
||||
folderInfo->SetFlags(mPrefFlags);
|
||||
|
||||
folderInfo->GetNumMessages(&mNumTotalMessages);
|
||||
folderInfo->GetNumNewMessages(&mNumUnreadMessages);
|
||||
|
||||
//These should be put in IMAP folder only.
|
||||
//folderInfo->GetImapTotalPendingMessages(&mNumPendingTotalMessages);
|
||||
//folderInfo->GetImapUnreadPendingMessages(&mNumPendingUnreadMessages);
|
||||
|
||||
folderInfo->GetCharacterSet(&mCharset);
|
||||
|
||||
if (db) {
|
||||
PRBool hasnew;
|
||||
nsresult rv;
|
||||
rv = db->HasNew(&hasnew);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!hasnew && mNumPendingUnreadMessages <= 0) {
|
||||
ClearFlag(MSG_FOLDER_FLAG_GOT_NEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (db)
|
||||
db->Close(PR_FALSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 changedFlags = oldFlags ^ newFlags;
|
||||
if((changedFlags & MSG_FLAG_READ) || (changedFlags & MSG_FLAG_REPLIED)
|
||||
|| (changedFlags & MSG_FLAG_FORWARDED)|| (changedFlags & MSG_FLAG_NEW))
|
||||
{
|
||||
rv = NotifyPropertyFlagChanged(item, "Status", oldFlags, newFlags);
|
||||
}
|
||||
else if((changedFlags & MSG_FLAG_MARKED))
|
||||
{
|
||||
rv = NotifyPropertyFlagChanged(item, "Flagged", oldFlags, newFlags);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
||||
{
|
||||
if (!aMsgDatabase || !mDatabase)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aMsgDatabase = mDatabase;
|
||||
NS_ADDREF(*aMsgDatabase);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> pMsgDBHdr;
|
||||
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(pMsgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
SendFlagNotifications(msgSupports, aOldFlags, aNewFlags);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> pMsgDBHdr;
|
||||
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(pMsgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
NotifyItemDeleted(msgSupports);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && msgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(msgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message));
|
||||
if(msgSupports)
|
||||
{
|
||||
NotifyItemAdded(msgSupports);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnParentChanged(nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *
|
||||
instigator)
|
||||
{
|
||||
if (mDatabase)
|
||||
{
|
||||
mDatabase->RemoveListener(this);
|
||||
mDatabase = null_nsCOMPtr();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::ManyHeadersToDownload(PRBool *retval)
|
||||
{
|
||||
PRInt32 numTotalMessages;
|
||||
|
||||
if (!retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mDatabase)
|
||||
*retval = PR_TRUE;
|
||||
else if (NS_SUCCEEDED(GetTotalMessages(PR_FALSE, &numTotalMessages)) && numTotalMessages <= 0)
|
||||
*retval = PR_TRUE;
|
||||
else
|
||||
*retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgDBFolder::ReadFromFolderCache(nsIMsgFolderCacheElement *element)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
char *charset;
|
||||
|
||||
element->GetInt32Property("flags", &mPrefFlags);
|
||||
element->GetInt32Property("totalMsgs", &mNumTotalMessages);
|
||||
element->GetInt32Property("totalUnreadMsgs", &mNumUnreadMessages);
|
||||
|
||||
element->GetStringProperty("charset", &charset);
|
||||
|
||||
#ifdef DEBUG_bienvenu1
|
||||
char *uri;
|
||||
|
||||
GetURI(&uri);
|
||||
printf("read total %ld for %s\n", mNumTotalMessages, uri);
|
||||
PR_Free(uri);
|
||||
#endif
|
||||
mCharset = charset;
|
||||
PR_FREEIF(charset);
|
||||
|
||||
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
||||
{
|
||||
nsCOMPtr <nsIEnumerator> aEnumerator;
|
||||
|
||||
nsresult rv = GetSubFolders(getter_AddRefs(aEnumerator));
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
char *uri = nsnull;
|
||||
rv = GetURI(&uri);
|
||||
|
||||
if (folderCache)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
||||
rv = folderCache->GetCacheElement(uri, PR_TRUE, getter_AddRefs(cacheElement));
|
||||
if (NS_SUCCEEDED(rv) && cacheElement)
|
||||
rv = WriteToFolderCacheElem(cacheElement);
|
||||
}
|
||||
PR_FREEIF(uri);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> aItem;
|
||||
|
||||
rv = aEnumerator->First();
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
return NS_OK; // it's OK, there are no sub-folders.
|
||||
|
||||
while(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = aEnumerator->CurrentItem(getter_AddRefs(aItem));
|
||||
if (NS_FAILED(rv)) break;
|
||||
nsCOMPtr<nsIMsgFolder> aMsgFolder(do_QueryInterface(aItem, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
if (folderCache)
|
||||
{
|
||||
rv = aMsgFolder->WriteToFolderCache(folderCache);
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = aEnumerator->Next();
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCacheElem(nsIMsgFolderCacheElement *element)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
element->SetInt32Property("flags", mPrefFlags);
|
||||
element->SetInt32Property("totalMsgs", mNumTotalMessages);
|
||||
element->SetInt32Property("totalUnreadMsgs", mNumUnreadMessages);
|
||||
|
||||
element->SetStringProperty("charset", (const char *) nsCAutoString(mCharset));
|
||||
|
||||
#ifdef DEBUG_bienvenu1
|
||||
char *uri;
|
||||
|
||||
GetURI(&uri);
|
||||
printf("writing total %ld for %s\n", mNumTotalMessages, uri);
|
||||
PR_Free(uri);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::MarkAllMessagesRead(void)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return mDatabase->MarkAllRead(nsnull);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::OnStartRunningUrl(nsIURI *aUrl)
|
||||
{
|
||||
NS_PRECONDITION(aUrl, "just a sanity check");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
|
||||
{
|
||||
NS_PRECONDITION(aUrl, "just a sanity check");
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(aUrl);
|
||||
if (mailUrl)
|
||||
{
|
||||
PRBool updatingFolder = PR_FALSE;
|
||||
if (NS_SUCCEEDED(mailUrl->GetUpdatingFolder(&updatingFolder)) && updatingFolder)
|
||||
{
|
||||
NotifyFolderLoaded();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
80
mozilla/mailnews/base/util/nsMsgDBFolder.h
Normal file
80
mozilla/mailnews/base/util/nsMsgDBFolder.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgDBFolder_h__
|
||||
#define nsMsgDBFolder_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgFolder.h"
|
||||
#include "nsIDBFolderInfo.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBChangeListener.h"
|
||||
#include "nsIUrlListener.h"
|
||||
|
||||
class nsIMsgFolderCacheElement;
|
||||
/*
|
||||
* nsMsgDBFolder
|
||||
* class derived from nsMsgFolder for those folders that use an nsIMsgDatabase
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgDBFolder: public nsMsgFolder,
|
||||
public nsIDBChangeListener,
|
||||
public nsIUrlListener
|
||||
{
|
||||
public:
|
||||
nsMsgDBFolder(void);
|
||||
virtual ~nsMsgDBFolder(void);
|
||||
NS_DECL_NSIDBCHANGELISTENER
|
||||
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD GetThreads(nsISimpleEnumerator** threadEnumerator);
|
||||
NS_IMETHOD GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread);
|
||||
NS_IMETHOD HasMessage(nsIMessage *message, PRBool *hasMessage);
|
||||
NS_IMETHOD GetCharset(PRUnichar * *aCharset);
|
||||
NS_IMETHOD SetCharset(const PRUnichar * aCharset);
|
||||
|
||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase** aMsgDatabase);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIURLLISTENER
|
||||
|
||||
NS_IMETHOD WriteToFolderCache(nsIMsgFolderCache *folderCache);
|
||||
NS_IMETHOD WriteToFolderCacheElem(nsIMsgFolderCacheElement *element);
|
||||
NS_IMETHOD ManyHeadersToDownload(PRBool *_retval);
|
||||
|
||||
NS_IMETHOD MarkAllMessagesRead(void);
|
||||
|
||||
protected:
|
||||
virtual nsresult ReadDBFolderInfo(PRBool force);
|
||||
virtual nsresult GetDatabase() = 0;
|
||||
virtual nsresult SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags);
|
||||
nsresult ReadFromFolderCache(nsIMsgFolderCacheElement *element);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
||||
nsString mCharset;
|
||||
PRBool mAddListener;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
1745
mozilla/mailnews/base/util/nsMsgFolder.cpp
Normal file
1745
mozilla/mailnews/base/util/nsMsgFolder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
268
mozilla/mailnews/base/util/nsMsgFolder.h
Normal file
268
mozilla/mailnews/base/util/nsMsgFolder.h
Normal file
@@ -0,0 +1,268 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Messenger folders.
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsMsgFolder_h__
|
||||
#define nsMsgFolder_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMsgFolder.h" /* include the interface we are going to support */
|
||||
#include "nsRDFResource.h"
|
||||
#include "nsIDBFolderInfo.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIURL.h"
|
||||
/*
|
||||
* MsgFolder
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgFolder: public nsRDFResource, public nsIMsgFolder
|
||||
{
|
||||
public:
|
||||
nsMsgFolder(void);
|
||||
virtual ~nsMsgFolder(void);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSICOLLECTION
|
||||
NS_DECL_NSIFOLDER
|
||||
// eventually this will be an instantiable class, and we should
|
||||
// use this macro:
|
||||
// NS_DECL_NSIMSGFOLDER
|
||||
|
||||
// right now a few of these methods are left abstract, and
|
||||
// are commented out below
|
||||
|
||||
// begin NS_DECL_NSIMSGFOLDER
|
||||
NS_IMETHOD AddUnique(nsISupports *element);
|
||||
NS_IMETHOD ReplaceElement(nsISupports *element, nsISupports *newElement);
|
||||
NS_IMETHOD GetMessages(nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD GetThreads(nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD UpdateFolder(void);
|
||||
NS_IMETHOD GetThreadForMessage(nsIMessage *message, nsIMsgThread **_retval);
|
||||
NS_IMETHOD HasMessage(nsIMessage *message, PRBool *_retval);
|
||||
NS_IMETHOD GetVisibleSubFolders(nsIEnumerator **_retval);
|
||||
NS_IMETHOD GetPrettiestName(PRUnichar * *aPrettiestName);
|
||||
NS_IMETHOD GetFolderURL(char * *aFolderURL);
|
||||
NS_IMETHOD GetDeleteIsMoveToTrash(PRBool *aDeleteIsMoveToTrash);
|
||||
NS_IMETHOD GetShowDeletedMessages(PRBool *aShowDeletedMessages);
|
||||
NS_IMETHOD GetServer(nsIMsgIncomingServer * *aServer);
|
||||
NS_IMETHOD GetIsServer(PRBool *aIsServer);
|
||||
NS_IMETHOD OnCloseFolder(void);
|
||||
NS_IMETHOD Delete(void);
|
||||
NS_IMETHOD DeleteSubFolders(nsISupportsArray *folders);
|
||||
NS_IMETHOD PropagateDelete(nsIMsgFolder *folder, PRBool deleteStorage);
|
||||
NS_IMETHOD RecursiveDelete(PRBool deleteStorage);
|
||||
NS_IMETHOD CreateSubfolder(const char *folderName);
|
||||
NS_IMETHOD Compact(void);
|
||||
NS_IMETHOD EmptyTrash(void);
|
||||
NS_IMETHOD Rename(const char *name);
|
||||
NS_IMETHOD Adopt(nsIMsgFolder *srcFolder, PRUint32 *outPos);
|
||||
NS_IMETHOD ContainsChildNamed(const char *name, PRBool *_retval);
|
||||
NS_IMETHOD IsAncestorOf(nsIMsgFolder *folder, PRBool *_retval);
|
||||
NS_IMETHOD GenerateUniqueSubfolderName(const char *prefix, nsIMsgFolder *otherFolder, char **_retval);
|
||||
NS_IMETHOD UpdateSummaryTotals(PRBool force);
|
||||
NS_IMETHOD SummaryChanged(void);
|
||||
NS_IMETHOD GetNumUnread(PRBool deep, PRInt32 *_retval);
|
||||
NS_IMETHOD GetTotalMessages(PRBool deep, PRInt32 *_retval);
|
||||
NS_IMETHOD GetExpungedBytesCount(PRUint32 *aExpungedBytesCount);
|
||||
NS_IMETHOD GetDeletable(PRBool *aDeletable);
|
||||
NS_IMETHOD GetCanCreateChildren(PRBool *aCanCreateChildren);
|
||||
NS_IMETHOD GetCanBeRenamed(PRBool *aCanBeRenamed);
|
||||
NS_IMETHOD GetRequiresCleanup(PRBool *aRequiresCleanup);
|
||||
NS_IMETHOD ClearRequiresCleanup(void);
|
||||
NS_IMETHOD ManyHeadersToDownload(PRBool *_retval);
|
||||
NS_IMETHOD GetKnowsSearchNntpExtension(PRBool *aKnowsSearchNntpExtension);
|
||||
NS_IMETHOD GetAllowsPosting(PRBool *aAllowsPosting);
|
||||
NS_IMETHOD GetDisplayRecipients(PRBool *aDisplayRecipients);
|
||||
NS_IMETHOD GetRelativePathName(char * *aRelativePathName);
|
||||
NS_IMETHOD GetSizeOnDisk(PRUint32 *aSizeOnDisk);
|
||||
NS_IMETHOD RememberPassword(const char *password);
|
||||
NS_IMETHOD GetRememberedPassword(char * *aRememberedPassword);
|
||||
NS_IMETHOD UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool *_retval);
|
||||
NS_IMETHOD GetUsername(char * *aUsername);
|
||||
NS_IMETHOD GetHostname(char * *aHostname);
|
||||
NS_IMETHOD SetFlag(PRUint32 flag);
|
||||
NS_IMETHOD ClearFlag(PRUint32 flag);
|
||||
NS_IMETHOD GetFlag(PRUint32 flag, PRBool *_retval);
|
||||
NS_IMETHOD ToggleFlag(PRUint32 flag);
|
||||
NS_IMETHOD OnFlagChange(PRUint32 flag);
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags);
|
||||
NS_IMETHOD GetFoldersWithFlag(PRUint32 flags, nsIMsgFolder **result, PRUint32 resultsize, PRUint32 *numFolders);
|
||||
NS_IMETHOD GetExpansionArray(nsISupportsArray *expansionArray);
|
||||
// NS_IMETHOD DeleteMessages(nsISupportsArray *message, nsITransactionManager *txnMgr, PRBool deleteStorage);
|
||||
NS_IMETHOD CopyMessages(nsIMsgFolder *srcFolder, nsISupportsArray *messages, PRBool isMove, nsITransactionManager *txnMgr, nsIMsgCopyServiceListener *listener);
|
||||
NS_IMETHOD CopyFileMessage(nsIFileSpec *fileSpec, nsIMessage *msgToReplace, PRBool isDraft, nsITransactionManager *txnMgr, nsIMsgCopyServiceListener *listener);
|
||||
NS_IMETHOD AcquireSemaphore(nsISupports *semHolder);
|
||||
NS_IMETHOD ReleaseSemaphore(nsISupports *semHolder);
|
||||
NS_IMETHOD TestSemaphore(nsISupports *semHolder, PRBool *_retval);
|
||||
NS_IMETHOD GetLocked(PRBool *aLocked);
|
||||
// NS_IMETHOD CreateMessageFromMsgDBHdr(nsIMsgDBHdr *msgDBHdr, nsIMessage **_retval);
|
||||
NS_IMETHOD GetNewMessages(void);
|
||||
// NS_IMETHOD WriteToFolderCache(nsIMsgFolderCache *folderCache);
|
||||
// NS_IMETHOD GetCharset(PRUnichar * *aCharset);
|
||||
// NS_IMETHOD SetCharset(const PRUnichar * aCharset);
|
||||
NS_IMETHOD GetBiffState(PRUint32 *aBiffState);
|
||||
NS_IMETHOD SetBiffState(PRUint32 aBiffState);
|
||||
NS_IMETHOD GetNumNewMessages(PRInt32 *aNumNewMessages);
|
||||
NS_IMETHOD SetNumNewMessages(PRInt32 aNumNewMessages);
|
||||
NS_IMETHOD GetNewMessagesNotificationDescription(PRUnichar * *aNewMessagesNotificationDescription);
|
||||
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
|
||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase * *aMsgDatabase);
|
||||
NS_IMETHOD GetPath(nsIFileSpec * *aPath);
|
||||
NS_IMETHOD MarkMessagesRead(nsISupportsArray *messages, PRBool markRead);
|
||||
NS_IMETHOD MarkAllMessagesRead(void);
|
||||
NS_IMETHOD MarkMessagesFlagged(nsISupportsArray *messages, PRBool markFlagged);
|
||||
NS_IMETHOD GetChildWithURI(const char *uri, PRBool deep, nsIMsgFolder **_retval);
|
||||
|
||||
// end NS_DECL_NSIMSGFOLDER
|
||||
|
||||
// nsRDFResource overrides
|
||||
NS_IMETHOD Init(const char* aURI);
|
||||
|
||||
#if 0
|
||||
static nsresult GetRoot(nsIMsgFolder* *result);
|
||||
#endif
|
||||
// Gets the URL that represents the given message. Returns a newly
|
||||
// created string that must be free'd using XP_FREE().
|
||||
// If the db is NULL, then returns a URL that represents the entire
|
||||
// folder as a whole.
|
||||
#ifdef HAVE_DB
|
||||
NS_IMETHOD BuildUrl(nsMsgDatabase *db, nsMsgKey key, char ** url);
|
||||
|
||||
// updates num messages and num unread - should be pure virtual
|
||||
// when I get around to implementing in all subclasses?
|
||||
NS_IMETHOD GetTotalMessagesInDB(PRUint32 *totalMessages) const; // How many messages in database.
|
||||
// These functions are used for tricking the front end into thinking that we have more
|
||||
// messages than are really in the DB. This is usually after and IMAP message copy where
|
||||
// we don't want to do an expensive select until the user actually opens that folder
|
||||
// These functions are called when MSG_Master::GetFolderLineById is populating a MSG_FolderLine
|
||||
// struct used by the FE
|
||||
int32 GetNumPendingUnread(PRBool deep = PR_FALSE);
|
||||
int32 GetNumPendingTotalMessages(PRBool deep = PR_FALSE);
|
||||
|
||||
void ChangeNumPendingUnread(int32 delta);
|
||||
void ChangeNumPendingTotalMessages(int32 delta);
|
||||
|
||||
|
||||
NS_IMETHOD SetFolderPrefFlags(PRUint32 flags);
|
||||
NS_IMETHOD GetFolderPrefFlags(PRUint32 *flags);
|
||||
|
||||
|
||||
NS_IMETHOD SetLastMessageLoaded(nsMsgKey lastMessageLoaded);
|
||||
NS_IMETHOD GetLastMessageLoaded();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_ADMINURL
|
||||
NS_IMETHOD GetAdminUrl(MWContext *context, MSG_AdminURLType type);
|
||||
NS_IMETHOD HaveAdminUrl(MSG_AdminURLType type, PRBool *hadAdminUrl);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_PANE
|
||||
NS_IMETHOD MarkAllRead(MSG_Pane *pane, PRBool deep);
|
||||
NS_IMETHOD SetFlagInAllFolderPanes(PRUint32 which);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NET
|
||||
NS_IMETHOD EscapeMessageId(const char *messageId, const char **escapeMessageID);
|
||||
NS_IMETHOD ShouldPerformOperationOffline(PRBool *performOffline);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CACHE
|
||||
virtual nsresult WriteToCache(XP_File);
|
||||
virtual nsresult ReadFromCache(char *);
|
||||
virtual PRBool IsCachable();
|
||||
void SkipCacheTokens(char **ppBuf, int numTokens);
|
||||
#endif
|
||||
|
||||
#ifdef DOES_FOLDEROPERATIONS
|
||||
int DownloadToTempFileAndUpload(MessageCopyInfo *copyInfo, nsMsgKeyArray &keysToSave, MSG_FolderInfo *dstFolder, nsMsgDatabase *sourceDB);
|
||||
void UpdateMoveCopyStatus(MWContext *context, PRBool isMove, int32 curMsgCount, int32 totMessages);
|
||||
#endif
|
||||
|
||||
virtual nsresult GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgDatabase **db) = 0;
|
||||
|
||||
|
||||
NS_IMETHOD MatchName(nsString *name, PRBool *matches);
|
||||
|
||||
|
||||
protected:
|
||||
nsresult NotifyPropertyChanged(char *property, char* oldValue, char* newValue);
|
||||
nsresult NotifyPropertyFlagChanged(nsISupports *item, char *property, PRUint32 oldValue,
|
||||
PRUint32 newValue);
|
||||
nsresult NotifyItemAdded(nsISupports *item);
|
||||
nsresult NotifyItemDeleted(nsISupports *item);
|
||||
|
||||
nsresult NotifyFolderLoaded();
|
||||
// this is a little helper function that is not part of the public interface.
|
||||
// we use it to get the IID of the incoming server for the derived folder.
|
||||
// w/out a function like this we would have to implement GetServer in each
|
||||
// derived folder class.
|
||||
virtual const char* GetIncomingServerType() = 0;
|
||||
|
||||
protected:
|
||||
PRUint32 mFlags;
|
||||
nsIFolder *mParent; //This won't be refcounted for ownership reasons.
|
||||
PRInt32 mNumUnreadMessages; /* count of unread messages (-1 means
|
||||
unknown; -2 means unknown but we already
|
||||
tried to find out.) */
|
||||
PRInt32 mNumTotalMessages; /* count of existing messages. */
|
||||
nsCOMPtr<nsISupportsArray> mSubFolders;
|
||||
nsVoidArray *mListeners; //This can't be an nsISupportsArray because due to
|
||||
//ownership issues, listeners can't be AddRef'd
|
||||
|
||||
PRInt32 mPrefFlags; // prefs like MSG_PREF_OFFLINE, MSG_PREF_ONE_PANE, etc
|
||||
nsISupports *mSemaphoreHolder; // set when the folder is being written to
|
||||
//Due to ownership issues, this won't be AddRef'd.
|
||||
|
||||
nsIMsgIncomingServer* m_server; //this won't be addrefed....ownership issue here
|
||||
|
||||
#ifdef HAVE_DB
|
||||
nsMsgKey m_lastMessageLoaded;
|
||||
#endif
|
||||
// These values are used for tricking the front end into thinking that we have more
|
||||
// messages than are really in the DB. This is usually after and IMAP message copy where
|
||||
// we don't want to do an expensive select until the user actually opens that folder
|
||||
PRInt32 mNumPendingUnreadMessages;
|
||||
PRInt32 mNumPendingTotalMessages;
|
||||
|
||||
PRUint32 mBiffState;
|
||||
PRInt32 mNumNewBiffMessages;
|
||||
|
||||
PRBool mIsCachable;
|
||||
|
||||
//
|
||||
// stuff from the uri
|
||||
//
|
||||
|
||||
PRBool mIsServer;
|
||||
nsString mName;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
598
mozilla/mailnews/base/util/nsMsgGroupRecord.cpp
Normal file
598
mozilla/mailnews/base/util/nsMsgGroupRecord.cpp
Normal file
@@ -0,0 +1,598 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsMsgGroupRecord.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
// mscott: this is lame...I know....
|
||||
#define MK_OUT_OF_MEMORY 1
|
||||
|
||||
const PRUint32 F_ISGROUP = 0x00000001;
|
||||
const PRUint32 F_EXPANDED = 0x00000002;
|
||||
const PRUint32 F_CATCONT = 0x00000004;
|
||||
const PRUint32 F_VIRTUAL = 0x00000008;
|
||||
const PRUint32 F_DIRTY = 0x00000010;
|
||||
const PRUint32 F_DESCENDENTSLOADED = 0x00000020;
|
||||
const PRUint32 F_HTMLOKGROUP = 0x00000040;
|
||||
const PRUint32 F_HTMLOKTREE = 0x00000080;
|
||||
const PRUint32 F_NEEDEXTRAINFO = 0x00000100;
|
||||
const PRUint32 F_DOESNOTEXIST = 0x00000200;
|
||||
const PRUint32 RUNTIMEFLAGS = // Flags to be sure *not* to write to disk.
|
||||
F_DIRTY | F_DESCENDENTSLOADED | F_EXPANDED;
|
||||
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::GroupNameCompare(const char* name1, const char* name2,
|
||||
char delimiter, PRBool caseInsensitive)
|
||||
{
|
||||
if (caseInsensitive)
|
||||
{
|
||||
while (*name1 && (nsCRT::ToUpper(*name1) == nsCRT::ToUpper(*name2))) {
|
||||
name1++;
|
||||
name2++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*name1 && *name1 == *name2) {
|
||||
name1++;
|
||||
name2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*name1 && *name2) {
|
||||
if (*name1 == delimiter) return -1;
|
||||
if (*name2 == delimiter) return 1;
|
||||
}
|
||||
|
||||
if (caseInsensitive)
|
||||
return int(nsCRT::ToUpper(*name1)) - int(nsCRT::ToUpper(*name2));
|
||||
else
|
||||
return int(*name1) - int(*name2);
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::Create(nsMsgGroupRecord* parent, const char* partname,
|
||||
PRInt64 aTime, PRInt32 uniqueid, PRInt32 fileoffset)
|
||||
{
|
||||
nsMsgGroupRecord* result = new nsMsgGroupRecord(parent, partname,
|
||||
aTime, uniqueid, fileoffset);
|
||||
if (result && partname && !result->m_partname) {
|
||||
// We ran out of memory.
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
result->InitializeSibling();
|
||||
return result;
|
||||
}
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgGroupRecord);
|
||||
|
||||
nsMsgGroupRecord::nsMsgGroupRecord(nsMsgGroupRecord* parent, const char* partname,
|
||||
PRInt64 aTime, PRInt32 uniqueid, PRInt32 fileoffset,
|
||||
char delimiter /* = '.' */)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgGroupRecord);
|
||||
int length;
|
||||
m_prettyname = NULL;
|
||||
m_parent = parent;
|
||||
m_children = NULL;
|
||||
m_sibling = NULL;
|
||||
m_flags = 0;
|
||||
m_partname = NULL;
|
||||
m_addtime = aTime;
|
||||
m_uniqueId = uniqueid;
|
||||
m_fileoffset = fileoffset;
|
||||
m_delimiter = delimiter;
|
||||
if (partname) {
|
||||
length = PL_strlen(partname);
|
||||
// PR_ASSERT(parent != NULL);
|
||||
m_partname = new char [length + 1];
|
||||
if (!m_partname) {
|
||||
m_parent = NULL;
|
||||
return;
|
||||
}
|
||||
PL_strcpy(m_partname, partname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord::~nsMsgGroupRecord()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsMsgGroupRecord);
|
||||
delete [] m_partname;
|
||||
m_partname = NULL;
|
||||
delete [] m_prettyname;
|
||||
m_prettyname = NULL;
|
||||
while (m_children) {
|
||||
delete m_children;
|
||||
}
|
||||
m_children = NULL;
|
||||
if (m_parent) {
|
||||
nsMsgGroupRecord** ptr;
|
||||
for (ptr = &(m_parent->m_children);
|
||||
*ptr;
|
||||
ptr = &((*ptr)->m_sibling)) {
|
||||
if (*ptr == this) {
|
||||
*ptr = m_sibling;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsMsgGroupRecord::InitializeSibling()
|
||||
{
|
||||
if (m_parent) {
|
||||
PR_ASSERT(m_partname != NULL);
|
||||
nsMsgGroupRecord** ptr;
|
||||
for (ptr = &(m_parent->m_children) ; *ptr ; ptr = &((*ptr)->m_sibling)) {
|
||||
int comp = GroupNameCompare((*ptr)->m_partname, m_partname, m_delimiter, IsIMAPGroupRecord());
|
||||
PR_ASSERT(comp != 0);
|
||||
if (comp >= 0) break;
|
||||
}
|
||||
m_sibling = *ptr;
|
||||
*ptr = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::FindDescendant(const char* name)
|
||||
{
|
||||
if (!name || !*name) return this;
|
||||
char* ptr = PL_strchr(name, m_delimiter);
|
||||
if (ptr) *ptr = '\0';
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
if (PL_strcmp(child->m_partname, name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr++ = m_delimiter;
|
||||
if (child) {
|
||||
return child->FindDescendant(ptr);
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetSiblingOrAncestorSibling()
|
||||
{
|
||||
if (m_sibling) return m_sibling;
|
||||
if (m_parent) return m_parent->GetSiblingOrAncestorSibling();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetNextAlphabetic()
|
||||
{
|
||||
nsMsgGroupRecord* result;
|
||||
if (m_children) result = m_children;
|
||||
else result = GetSiblingOrAncestorSibling();
|
||||
#ifdef DEBUG_slowAndParanoid
|
||||
if (result) {
|
||||
char* ptr1 = GetFullName();
|
||||
char* ptr2 = result->GetFullName();
|
||||
PR_ASSERT(GroupNameCompare(ptr1, ptr2) < 0);
|
||||
delete [] ptr1;
|
||||
delete [] ptr2;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetNextAlphabeticNoCategories()
|
||||
{
|
||||
if (IsCategoryContainer()) {
|
||||
return GetSiblingOrAncestorSibling();
|
||||
} else {
|
||||
return GetNextAlphabetic();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::GetFullName()
|
||||
{
|
||||
int length = 0;
|
||||
nsMsgGroupRecord* ptr;
|
||||
for (ptr = this ; ptr ; ptr = ptr->m_parent) {
|
||||
if (ptr->m_partname) length += PL_strlen(ptr->m_partname) + 1;
|
||||
}
|
||||
PR_ASSERT(length > 0);
|
||||
if (length <= 0) return NULL;
|
||||
char* result = new char [length];
|
||||
if (result) {
|
||||
SuckInName(result);
|
||||
PR_ASSERT(int(PL_strlen(result)) + 1 == length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::SuckInName(char* ptr)
|
||||
{
|
||||
if (m_parent && m_parent->m_partname) {
|
||||
ptr = m_parent->SuckInName(ptr);
|
||||
*ptr++ = m_delimiter;
|
||||
}
|
||||
PL_strcpy(ptr, m_partname);
|
||||
return ptr + PL_strlen(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetPrettyName(const char* name)
|
||||
{
|
||||
if (name == NULL && m_prettyname == NULL) return 0;
|
||||
m_flags |= F_DIRTY;
|
||||
delete [] m_prettyname;
|
||||
m_prettyname = NULL;
|
||||
if (!name || !*name) {
|
||||
return 0;
|
||||
}
|
||||
int length = PL_strlen(name);
|
||||
m_prettyname = new char [length + 1];
|
||||
if (!m_prettyname) {
|
||||
return MK_OUT_OF_MEMORY;
|
||||
}
|
||||
PL_strcpy(m_prettyname, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsCategory()
|
||||
{
|
||||
return GetCategoryContainer() != NULL;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsCategoryContainer()
|
||||
{
|
||||
return (m_flags & F_CATCONT) != 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::NeedsExtraInfo()
|
||||
{
|
||||
return (m_flags & F_NEEDEXTRAINFO) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetNeedsExtraInfo(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_NEEDEXTRAINFO, value);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsCategoryContainer(PRBool value)
|
||||
{
|
||||
// refuse to set a group to be a category container if it has a parent
|
||||
// that's a category container.
|
||||
if (! (value && GetCategoryContainer()))
|
||||
return TweakFlag(F_CATCONT, value);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetCategoryContainer()
|
||||
{
|
||||
if (IsCategoryContainer()) return NULL;
|
||||
for (nsMsgGroupRecord* ptr = m_parent ; ptr ; ptr = ptr->m_parent) {
|
||||
if (ptr->IsCategoryContainer()) return ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMsgGroupRecord::IsVirtual(PRBool *retval)
|
||||
{
|
||||
*retval =( (m_flags & F_VIRTUAL) != 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgGroupRecord::SetIsVirtual(PRBool value)
|
||||
{
|
||||
TweakFlag(F_VIRTUAL, value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsExpanded()
|
||||
{
|
||||
return (m_flags & F_EXPANDED) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsExpanded(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_EXPANDED, value);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsHTMLOKGroup()
|
||||
{
|
||||
return (m_flags & F_HTMLOKGROUP) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsHTMLOKGroup(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_HTMLOKGROUP, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsHTMLOKTree()
|
||||
{
|
||||
return (m_flags & F_HTMLOKTREE) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsHTMLOKTree(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_HTMLOKTREE, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsGroup()
|
||||
{
|
||||
return (m_flags & F_ISGROUP) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsGroup(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_ISGROUP, value);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsDescendentsLoaded()
|
||||
{
|
||||
return (m_flags & F_DESCENDENTSLOADED) != 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsDescendentsLoaded(PRBool value)
|
||||
{
|
||||
PR_ASSERT(value); // No reason we'd ever unset this.
|
||||
TweakFlag(F_DESCENDENTSLOADED, PR_TRUE);
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
child->SetIsDescendentsLoaded(value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool nsMsgGroupRecord::DoesNotExistOnServer()
|
||||
{
|
||||
return (m_flags & F_DOESNOTEXIST) != 0;
|
||||
}
|
||||
|
||||
int nsMsgGroupRecord::SetDoesNotExistOnServer(PRBool value)
|
||||
{
|
||||
if (value) // turn off group flag if doesn't exist on server.
|
||||
TweakFlag(F_ISGROUP, PR_FALSE);
|
||||
return TweakFlag(F_DOESNOTEXIST, value);
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::TweakFlag(PRUint32 flagbit, PRBool value)
|
||||
{
|
||||
if (value) {
|
||||
if (!(m_flags & flagbit)) {
|
||||
m_flags |= flagbit;
|
||||
if (flagbit & ~RUNTIMEFLAGS)
|
||||
m_flags |= F_DIRTY;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (m_flags & flagbit) {
|
||||
m_flags &= ~flagbit;
|
||||
if (flagbit & ~RUNTIMEFLAGS)
|
||||
m_flags |= F_DIRTY;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
nsMsgGroupRecord::GetNumKids()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
if (IsIMAPGroupRecord())
|
||||
result++;
|
||||
else
|
||||
if (child->m_flags & F_ISGROUP) result++;
|
||||
|
||||
if (!IsIMAPGroupRecord())
|
||||
result += child->GetNumKids();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::GetSaveString()
|
||||
{
|
||||
char* pretty = NULL;
|
||||
char* result = nsnull;
|
||||
|
||||
if (m_prettyname) {
|
||||
pretty = nsEscape(m_prettyname, url_XAlphas);
|
||||
if (!pretty) return NULL;
|
||||
}
|
||||
char* fullname = GetFullName();
|
||||
if (!fullname) return NULL; {
|
||||
long nAddTime;
|
||||
LL_L2I(nAddTime, m_addtime);
|
||||
result = PR_smprintf("%s,%s,%lx,%lx,%lx" MSG_LINEBREAK,
|
||||
fullname, pretty ? pretty : "",
|
||||
(long) (m_flags & ~RUNTIMEFLAGS),
|
||||
nAddTime,
|
||||
(long) m_uniqueId);
|
||||
}
|
||||
delete [] fullname;
|
||||
if (pretty) nsCRT::free(pretty);
|
||||
m_flags &= ~F_DIRTY;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsDirty()
|
||||
{
|
||||
return (m_flags & F_DIRTY) != 0;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
nsMsgGroupRecord::GetDepth()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsMsgGroupRecord* tmp = m_parent;
|
||||
while (tmp) {
|
||||
tmp = tmp->m_parent;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::Create(nsMsgGroupRecord* parent, const char* saveline,
|
||||
PRInt32 savelinelength, PRInt32 fileoffset)
|
||||
{
|
||||
char* tmp;
|
||||
char* ptr;
|
||||
char* endptr;
|
||||
char* partname;
|
||||
char* prettyname;
|
||||
PRInt32 flags;
|
||||
PRInt32 addtime;
|
||||
PRInt32 uniqueid;
|
||||
nsMsgGroupRecord* result = NULL;
|
||||
|
||||
if (savelinelength < 0) savelinelength = PL_strlen(saveline);
|
||||
tmp = (char*) PR_Malloc(savelinelength + 1);
|
||||
if (!tmp) return NULL;
|
||||
PL_strncpy(tmp, saveline, savelinelength);
|
||||
tmp[savelinelength] = '\0';
|
||||
ptr = PL_strchr(tmp, ',');
|
||||
PR_ASSERT(ptr);
|
||||
if (!ptr) goto FAIL;
|
||||
*ptr++ = '\0';
|
||||
partname = PL_strrchr(tmp, '.');
|
||||
if (!partname) partname = tmp;
|
||||
else partname++;
|
||||
|
||||
#ifdef DEBUG_slowAndParanoid
|
||||
if (parent->m_partname) {
|
||||
char* parentname = parent->GetFullName();
|
||||
PR_ASSERT(partname > tmp && partname[-1] == '.');
|
||||
partname[-1] = '\0';
|
||||
PR_ASSERT(PL_strcmp(parentname, tmp) == 0);
|
||||
partname[-1] = '.';
|
||||
delete [] parentname;
|
||||
parentname = NULL;
|
||||
} else {
|
||||
PR_ASSERT(partname == tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
prettyname = nsUnescape(ptr);
|
||||
|
||||
ptr = endptr;
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
flags = strtol(ptr, NULL, 16);
|
||||
|
||||
ptr = endptr;
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
addtime = strtol(ptr, NULL, 16);
|
||||
|
||||
ptr = endptr;
|
||||
uniqueid = strtol(ptr, NULL, 16);
|
||||
|
||||
PRInt64 llAddtime;
|
||||
LL_I2L(llAddtime, addtime);
|
||||
result = Create(parent, partname, llAddtime, uniqueid, fileoffset);
|
||||
if (result) {
|
||||
PRBool maybeCategoryContainer = flags & F_CATCONT;
|
||||
flags &= ~F_CATCONT;
|
||||
result->m_flags = flags;
|
||||
if (maybeCategoryContainer)
|
||||
result->SetIsCategoryContainer(PR_TRUE);
|
||||
if (prettyname && *prettyname) result->SetPrettyName(prettyname);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
PR_Free(tmp);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
160
mozilla/mailnews/base/util/nsMsgGroupRecord.h
Normal file
160
mozilla/mailnews/base/util/nsMsgGroupRecord.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
// This class should only be used by the subscribe UI and by newshost.cpp.
|
||||
// And, well, a bit by the category code. Everyone else should use the stuff
|
||||
// in newshost.h.
|
||||
|
||||
#ifndef _nsMsgGroupRecord_h_
|
||||
#define _nsMsgGroupRecord_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIMAPGroupRecord;
|
||||
|
||||
class NS_MSG_BASE nsMsgGroupRecord {
|
||||
public:
|
||||
static nsMsgGroupRecord* Create(nsMsgGroupRecord* parent,
|
||||
const char* partname,
|
||||
PRInt64 m_addtime,
|
||||
PRInt32 uniqueid,
|
||||
PRInt32 fileoffset);
|
||||
static nsMsgGroupRecord* Create(nsMsgGroupRecord* parent,
|
||||
const char* saveline,
|
||||
PRInt32 savelinelength,
|
||||
PRInt32 fileoffset);
|
||||
|
||||
|
||||
virtual void InitializeSibling();
|
||||
virtual PRBool IsIMAPGroupRecord() { return PR_FALSE; }
|
||||
virtual nsIMAPGroupRecord *GetIMAPGroupRecord() { return 0; }
|
||||
|
||||
// This is just like PL_strcmp(), except it works on news group names.
|
||||
// A container groupname is always less than any contained groups.
|
||||
// So, "netscape.devs-client-technical" > "netscape.devs.directory", even
|
||||
// though PL_strcmp says otherwise. (YICK!)
|
||||
static int GroupNameCompare(const char* name1,
|
||||
const char* name2,
|
||||
char delimiter = '.',
|
||||
PRBool caseInsensitive = PR_FALSE);
|
||||
|
||||
|
||||
virtual ~nsMsgGroupRecord();
|
||||
|
||||
nsMsgGroupRecord* FindDescendant(const char* name);
|
||||
|
||||
nsMsgGroupRecord* GetParent() {return m_parent;}
|
||||
nsMsgGroupRecord* GetChildren() {return m_children;}
|
||||
nsMsgGroupRecord* GetSibling() {return m_sibling;}
|
||||
nsMsgGroupRecord* GetSiblingOrAncestorSibling();
|
||||
nsMsgGroupRecord* GetNextAlphabetic();
|
||||
|
||||
nsMsgGroupRecord* GetNextAlphabeticNoCategories();
|
||||
|
||||
const char* GetPartName() {return m_partname;}
|
||||
|
||||
// The resulting string must be free'd using delete[].
|
||||
char* GetFullName();
|
||||
|
||||
const char* GetPrettyName() {return m_prettyname;}
|
||||
int SetPrettyName(const char* prettyname);
|
||||
|
||||
PRInt64 GetAddTime() {return m_addtime;}
|
||||
|
||||
virtual PRBool IsCategory();
|
||||
virtual PRBool IsCategoryContainer();
|
||||
virtual int SetIsCategoryContainer(PRBool value);
|
||||
|
||||
nsMsgGroupRecord* GetCategoryContainer();
|
||||
|
||||
// Get/Set whether this is a virtual newsgroup.
|
||||
nsresult IsVirtual(PRBool *retval);
|
||||
nsresult SetIsVirtual(PRBool value);
|
||||
|
||||
// Get/Set whether this is really a newsgroup (and not just a container
|
||||
// for newsgroups).
|
||||
virtual PRBool IsGroup();
|
||||
int SetIsGroup(PRBool value);
|
||||
|
||||
PRBool IsDescendentsLoaded();
|
||||
int SetIsDescendentsLoaded(PRBool value);
|
||||
|
||||
PRBool IsExpanded();
|
||||
int SetIsExpanded(PRBool value);
|
||||
|
||||
PRBool IsHTMLOKGroup();
|
||||
int SetIsHTMLOKGroup(PRBool value);
|
||||
|
||||
PRBool IsHTMLOKTree();
|
||||
int SetIsHTMLOKTree(PRBool value);
|
||||
|
||||
PRBool NeedsExtraInfo();
|
||||
int SetNeedsExtraInfo(PRBool value);
|
||||
|
||||
PRBool DoesNotExistOnServer();
|
||||
int SetDoesNotExistOnServer(PRBool value);
|
||||
|
||||
PRInt32 GetUniqueID() {return m_uniqueId;}
|
||||
|
||||
PRInt32 GetFileOffset() {return m_fileoffset;}
|
||||
int SetFileOffset(PRInt32 value) {m_fileoffset = value; return 0;}
|
||||
|
||||
// Get the number of descendents (not including ourself) that are
|
||||
// really newsgroups.
|
||||
PRInt32 GetNumKids();
|
||||
|
||||
// Gets the string that represents this group in the save file. The
|
||||
// resulting string must be free'd with PR_Free().
|
||||
char* GetSaveString();
|
||||
|
||||
PRBool IsDirty(); // Whether this record has had changes made
|
||||
// to it. Cleared by calls to GetSaveString().
|
||||
|
||||
PRInt32 GetDepth(); // Returns how deep in the heirarchy we are.
|
||||
// Basically, the number of dots in the full
|
||||
// newsgroup name, plus 1.
|
||||
virtual char GetHierarchySeparator() { return '.'; }
|
||||
|
||||
protected:
|
||||
nsMsgGroupRecord(nsMsgGroupRecord* parent,
|
||||
const char* partname,
|
||||
PRInt64 m_addtime,
|
||||
PRInt32 uniqueid,
|
||||
PRInt32 fileoffset,
|
||||
char delimiter = '.');
|
||||
int TweakFlag(PRUint32 flagbit, PRBool value);
|
||||
char* SuckInName(char* ptr);
|
||||
|
||||
char* m_partname;
|
||||
char* m_prettyname;
|
||||
nsMsgGroupRecord* m_parent;
|
||||
nsMsgGroupRecord* m_children;
|
||||
nsMsgGroupRecord* m_sibling;
|
||||
PRUint32 m_flags;
|
||||
PRInt64 m_addtime;
|
||||
PRInt32 m_uniqueId;
|
||||
PRInt32 m_fileoffset;
|
||||
char m_delimiter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _grec_h_ */
|
||||
363
mozilla/mailnews/base/util/nsMsgI18N.cpp
Normal file
363
mozilla/mailnews/base/util/nsMsgI18N.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
// as does this
|
||||
#define NS_IMPL_IDS
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "msgCore.h"
|
||||
#include "rosetta_mailnews.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIEntityConverter.h"
|
||||
#include "nsISaveAsCharset.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kCMimeConverterCID, NS_MIME_CONVERTER_CID);
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
|
||||
static NS_DEFINE_CID(kSaveAsCharsetCID, NS_SAVEASCHARSET_CID);
|
||||
|
||||
//
|
||||
// International functions necessary for composition
|
||||
//
|
||||
|
||||
// Convert an unicode string to a C string with a given charset.
|
||||
nsresult ConvertFromUnicode(const nsString& aCharset,
|
||||
const nsString& inString,
|
||||
char** outCString)
|
||||
{
|
||||
nsresult res;
|
||||
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, ccm, kCharsetConverterManagerCID, &res);
|
||||
|
||||
if(NS_SUCCEEDED(res) && (nsnull != ccm)) {
|
||||
nsIUnicodeEncoder* encoder = nsnull;
|
||||
nsString convCharset;
|
||||
|
||||
// map to converter charset
|
||||
if (aCharset.EqualsIgnoreCase("us-ascii")) {
|
||||
convCharset.SetString("iso-8859-1");
|
||||
}
|
||||
else {
|
||||
convCharset = aCharset;
|
||||
}
|
||||
|
||||
// get an unicode converter
|
||||
res = ccm->GetUnicodeEncoder(&convCharset, &encoder);
|
||||
if(NS_SUCCEEDED(res) && (nsnull != encoder)) {
|
||||
PRUnichar *unichars = (PRUnichar *) inString.GetUnicode();
|
||||
PRInt32 unicharLength = inString.Length();
|
||||
PRInt32 dstLength;
|
||||
res = encoder->GetMaxLength(unichars, unicharLength, &dstLength);
|
||||
// allocale an output buffer
|
||||
*outCString = (char *) PR_Malloc(dstLength + 1);
|
||||
if (nsnull != *outCString) {
|
||||
PRInt32 oldUnicharLength = unicharLength;
|
||||
char *tempCString = *outCString;
|
||||
PRInt32 totalCLength = 0;
|
||||
while (1) {
|
||||
res = encoder->Convert(unichars, &unicharLength, tempCString, &dstLength);
|
||||
|
||||
// increment for destination
|
||||
tempCString += dstLength;
|
||||
totalCLength += dstLength;
|
||||
|
||||
// break: this is usually the case
|
||||
// source length <= zero and no error or unrecoverable error
|
||||
if (0 >= unicharLength || NS_ERROR_UENC_NOMAPPING != res) {
|
||||
break;
|
||||
}
|
||||
// could not map unicode to the destination charset, skip one unichar and continue
|
||||
// increment for source unicode, skip one unichar
|
||||
unichars += unicharLength + 1;
|
||||
oldUnicharLength -= (unicharLength + 1);
|
||||
unicharLength = oldUnicharLength;
|
||||
// estimate target length again
|
||||
(void) encoder->GetMaxLength(unichars, unicharLength, &dstLength);
|
||||
}
|
||||
(*outCString)[totalCLength] = '\0';
|
||||
}
|
||||
else {
|
||||
res = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_IF_RELEASE(encoder);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Convert a C string to an unicode string.
|
||||
nsresult ConvertToUnicode(const nsString& aCharset,
|
||||
const char* inCString,
|
||||
nsString& outString)
|
||||
{
|
||||
nsresult res;
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, ccm, kCharsetConverterManagerCID, &res);
|
||||
|
||||
if(NS_SUCCEEDED(res) && (nsnull != ccm)) {
|
||||
nsIUnicodeDecoder* decoder = nsnull;
|
||||
PRUnichar *unichars;
|
||||
PRInt32 unicharLength;
|
||||
nsString convCharset;
|
||||
|
||||
// map to converter charset
|
||||
if (aCharset.EqualsIgnoreCase("us-ascii")) {
|
||||
convCharset.SetString("iso-8859-1");
|
||||
}
|
||||
else {
|
||||
convCharset = aCharset;
|
||||
}
|
||||
// get an unicode converter
|
||||
res = ccm->GetUnicodeDecoder(&convCharset, &decoder);
|
||||
if(NS_SUCCEEDED(res) && (nsnull != decoder)) {
|
||||
PRInt32 srcLen = PL_strlen(inCString);
|
||||
res = decoder->GetMaxLength(inCString, srcLen, &unicharLength);
|
||||
// allocale an output buffer
|
||||
unichars = (PRUnichar *) PR_Malloc(unicharLength * sizeof(PRUnichar));
|
||||
if (unichars != nsnull) {
|
||||
// convert to unicode
|
||||
res = decoder->Convert(inCString, &srcLen, unichars, &unicharLength);
|
||||
outString.SetString(unichars, unicharLength);
|
||||
PR_Free(unichars);
|
||||
}
|
||||
else {
|
||||
res = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_IF_RELEASE(decoder);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Charset to be used for the internatl processing.
|
||||
const char *msgCompHeaderInternalCharset()
|
||||
{
|
||||
// UTF-8 is a super set of us-ascii.
|
||||
// We can use the same string manipulation methods as us-ascii without breaking non us-ascii characters.
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
// MIME encoder, output string should be freed by PR_FREE
|
||||
char * nsMsgI18NEncodeMimePartIIStr(const char *header, const char *charset, PRBool bUseMime)
|
||||
{
|
||||
// No MIME, just duplicate the string.
|
||||
if (PR_FALSE == bUseMime) {
|
||||
return PL_strdup(header);
|
||||
}
|
||||
|
||||
char *encodedString = nsnull;
|
||||
nsIMimeConverter *converter;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
|
||||
nsCOMTypeInfo<nsIMimeConverter>::GetIID(), (void **)&converter);
|
||||
if (NS_SUCCEEDED(res) && nsnull != converter) {
|
||||
res = converter->EncodeMimePartIIStr_UTF8(header, charset, kMIME_ENCODED_WORD_SIZE, &encodedString);
|
||||
NS_RELEASE(converter);
|
||||
}
|
||||
return NS_SUCCEEDED(res) ? encodedString : nsnull;
|
||||
}
|
||||
|
||||
// MIME decoder
|
||||
nsresult nsMsgI18NDecodeMimePartIIStr(const nsString& header, nsString& charset, nsString& decodedString)
|
||||
{
|
||||
nsIMimeConverter *converter;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
|
||||
nsCOMTypeInfo<nsIMimeConverter>::GetIID(), (void **)&converter);
|
||||
if (NS_SUCCEEDED(res) && nsnull != converter) {
|
||||
res = converter->DecodeMimePartIIStr(header, charset, decodedString);
|
||||
NS_RELEASE(converter);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Get a default mail character set.
|
||||
char * nsMsgI18NGetDefaultMailCharset()
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
char * retVal = nsnull;
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &res);
|
||||
if (nsnull != prefs && NS_SUCCEEDED(res))
|
||||
{
|
||||
char *prefValue;
|
||||
res = prefs->CopyCharPref("intl.character_set_name", &prefValue);
|
||||
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
//TODO: map to mail charset (e.g. Shift_JIS -> ISO-2022-JP) bug#3941.
|
||||
retVal = prefValue;
|
||||
}
|
||||
else
|
||||
retVal = PL_strdup("iso-8859-1");
|
||||
}
|
||||
|
||||
return (nsnull != retVal) ? retVal : PL_strdup("iso-8859-1");
|
||||
}
|
||||
|
||||
// Return True if a charset is stateful (e.g. JIS).
|
||||
PRBool nsMsgI18Nstateful_charset(const char *charset)
|
||||
{
|
||||
//TODO: use charset manager's service
|
||||
return (PL_strcasecmp(charset, "iso-2022-jp") == 0);
|
||||
}
|
||||
|
||||
// Check 7bit in a given buffer.
|
||||
// This is expensive (both memory and performance).
|
||||
// The check would be very simple if applied to an unicode text (e.g. nsString or utf-8).
|
||||
// Possible optimazaion is to search ESC(0x1B) in case of iso-2022-jp and iso-2022-kr.
|
||||
// Or convert and check line by line.
|
||||
PRBool nsMsgI18N7bit_data_part(const char *charset, const char *inString, const PRUint32 size)
|
||||
{
|
||||
char *aCString;
|
||||
nsString aCharset(charset);
|
||||
nsString outString;
|
||||
nsresult res;
|
||||
|
||||
aCString = (char *) PR_Malloc(size + 1);
|
||||
if (nsnull != aCString) {
|
||||
PL_strncpy(aCString, inString, size); // make a C string
|
||||
res = ConvertToUnicode(aCharset, aCString, outString);
|
||||
PR_Free(aCString);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
for (PRInt32 i = 0; i < outString.Length(); i++) {
|
||||
if (outString.CharAt(i) > 127) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_TRUE; // all 7 bit
|
||||
}
|
||||
|
||||
// Simple parser to parse META charset.
|
||||
// It only supports the case when the description is within one line.
|
||||
const char *
|
||||
nsMsgI18NParseMetaCharset(nsFileSpec* fileSpec)
|
||||
{
|
||||
static char charset[65];
|
||||
char buffer[512];
|
||||
nsInputFileStream fileStream(*fileSpec);
|
||||
|
||||
*charset = '\0';
|
||||
|
||||
while (!fileStream.eof() && !fileStream.failed() &&
|
||||
fileStream.is_open()) {
|
||||
fileStream.readline(buffer, 512);
|
||||
if (*buffer == CR || *buffer == LF || *buffer == 0)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < (int)PL_strlen(buffer); i++) {
|
||||
buffer[i] = toupper(buffer[i]);
|
||||
}
|
||||
|
||||
if (PL_strstr(buffer, "/HEAD"))
|
||||
break;
|
||||
|
||||
if (PL_strstr(buffer, "META") &&
|
||||
PL_strstr(buffer, "HTTP-EQUIV") &&
|
||||
PL_strstr(buffer, "CONTENT-TYPE") &&
|
||||
PL_strstr(buffer, "CHARSET")
|
||||
)
|
||||
{
|
||||
char *cp = PL_strstr(PL_strstr(buffer, "CHARSET"), "=") + 1;
|
||||
char seps[] = " \"\'";
|
||||
char *token;
|
||||
char* newStr;
|
||||
token = nsCRT::strtok(cp, seps, &newStr);
|
||||
if (token != NULL)
|
||||
{
|
||||
PL_strcpy(charset, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return charset;
|
||||
}
|
||||
|
||||
nsresult nsMsgI18NConvertToEntity(const nsString& inString, nsString* outString)
|
||||
{
|
||||
nsresult res;
|
||||
|
||||
outString->SetString("");
|
||||
nsCOMPtr <nsIEntityConverter> entityConv;
|
||||
res = nsComponentManager::CreateInstance(kEntityConverterCID, NULL,
|
||||
nsIEntityConverter::GetIID(), getter_AddRefs(entityConv));
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
PRUnichar *entities = NULL;
|
||||
res = entityConv->ConvertToEntities(inString.GetUnicode(), nsIEntityConverter::html40Latin1, &entities);
|
||||
if (NS_SUCCEEDED(res) && (NULL != entities)) {
|
||||
outString->SetString(entities);
|
||||
nsAllocator::Free(entities);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult nsMsgI18NSaveAsCharset(const char* contentType, const char *charset, const PRUnichar* inString, char** outString)
|
||||
{
|
||||
NS_ASSERTION(contentType, "null ptr- contentType");
|
||||
NS_ASSERTION(charset, "null ptr- charset");
|
||||
NS_ASSERTION(outString, "null ptr- outString");
|
||||
if(!contentType || !charset || !outString)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*outString = NULL;
|
||||
|
||||
PRBool bTEXT_HTML = PR_FALSE;
|
||||
nsresult res;
|
||||
|
||||
if (!nsCRT::strcasecmp(contentType, TEXT_HTML)) {
|
||||
bTEXT_HTML = PR_TRUE;
|
||||
}
|
||||
else if (nsCRT::strcasecmp(contentType, TEXT_PLAIN)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE; // not supported type
|
||||
}
|
||||
|
||||
nsCOMPtr <nsISaveAsCharset> aConv; // charset converter plus entity, NCR generation
|
||||
res = nsComponentManager::CreateInstance(kSaveAsCharsetCID, NULL,
|
||||
nsISaveAsCharset::GetIID(), getter_AddRefs(aConv));
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
// attribute:
|
||||
// html text - charset conv then fallback to entity or NCR
|
||||
// plain text - charset conv then fallback to '?'
|
||||
res = aConv->Init(charset,
|
||||
bTEXT_HTML ?
|
||||
nsISaveAsCharset::attr_EntityAfterCharsetConv + nsISaveAsCharset::attr_FallbackDecimalNCR :
|
||||
nsISaveAsCharset::attr_plainTextDefault + nsISaveAsCharset::attr_FallbackQuestionMark,
|
||||
nsIEntityConverter::html40);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = aConv->Convert(inString, outString);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// RICHIE - not sure about this one?? need to see what it did in the old
|
||||
// world.
|
||||
char *
|
||||
nsMsgI18NGetAcceptLanguage(void)
|
||||
{
|
||||
return "en";
|
||||
}
|
||||
49
mozilla/mailnews/base/util/nsMsgI18N.h
Normal file
49
mozilla/mailnews/base/util/nsMsgI18N.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsMsgI18N_H_
|
||||
#define _nsMsgI18N_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
|
||||
NS_MSG_BASE char *nsMsgI18NEncodeMimePartIIStr(const char *header, const char *charset, PRBool bUseMime);
|
||||
NS_MSG_BASE PRBool nsMsgI18Nstateful_charset(const char *charset);
|
||||
NS_MSG_BASE PRBool nsMsgI18N7bit_data_part(const char *charset, const char *string, const PRUint32 size);
|
||||
NS_MSG_BASE char *nsMsgI18NGetAcceptLanguage(void);
|
||||
|
||||
NS_MSG_BASE const char *msgCompHeaderInternalCharset(void);
|
||||
|
||||
NS_MSG_BASE char * nsMsgI18NGetDefaultMailCharset(void);
|
||||
NS_MSG_BASE nsresult ConvertFromUnicode(const nsString& aCharset,
|
||||
const nsString& inString,
|
||||
char** outCString);
|
||||
NS_MSG_BASE nsresult ConvertToUnicode(const nsString& aCharset,
|
||||
const char* inCString,
|
||||
nsString& outString);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NDecodeMimePartIIStr(const nsString& header, nsString& charset, nsString& decodedString);
|
||||
|
||||
NS_MSG_BASE const char *nsMsgI18NParseMetaCharset(nsFileSpec* fileSpec);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NConvertToEntity(const nsString& inString, nsString* outString);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NSaveAsCharset(const char* contentType, const char* charset, const PRUnichar* inString, char** outString);
|
||||
|
||||
#endif /* _nsMsgI18N_H_ */
|
||||
356
mozilla/mailnews/base/util/nsMsgIdentity.cpp
Normal file
356
mozilla/mailnews/base/util/nsMsgIdentity.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
#include "nsMsgIdentity.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsMsgIdentity,
|
||||
nsIMsgIdentity,
|
||||
nsIShutdownListener)
|
||||
|
||||
nsMsgIdentity::nsMsgIdentity():
|
||||
m_signature(0),
|
||||
m_vCard(0),
|
||||
m_identityKey(0),
|
||||
m_prefs(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMsgIdentity::~nsMsgIdentity()
|
||||
{
|
||||
PR_FREEIF(m_identityKey);
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID,
|
||||
m_prefs,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getPrefService()
|
||||
{
|
||||
if (m_prefs) return NS_OK;
|
||||
return nsServiceManager::GetService(kPrefServiceCID,
|
||||
nsCOMTypeInfo<nsIPref>::GetIID(),
|
||||
(nsISupports**)&m_prefs,
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
/* called if the prefs service goes offline */
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::OnShutdown(const nsCID& aClass, nsISupports *service)
|
||||
{
|
||||
if (aClass.Equals(kPrefServiceCID)) {
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
|
||||
m_prefs = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* accessors for pulling values directly out of preferences
|
||||
* instead of member variables, etc
|
||||
*/
|
||||
|
||||
/* convert an identity key and preference name
|
||||
to mail.identity.<identityKey>.<prefName>
|
||||
*/
|
||||
char *
|
||||
nsMsgIdentity::getPrefName(const char *identityKey,
|
||||
const char *prefName)
|
||||
{
|
||||
return PR_smprintf("mail.identity.%s.%s", identityKey, prefName);
|
||||
}
|
||||
|
||||
// this will be slightly faster than the above, and allows
|
||||
// the "default" identity preference root to be set in one place
|
||||
char *
|
||||
nsMsgIdentity::getDefaultPrefName(const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.identity.default.%s", fullPrefName);
|
||||
}
|
||||
|
||||
/* The following are equivalent to the nsIPref's Get/CopyXXXPref
|
||||
except they construct the preference name with the above function
|
||||
*/
|
||||
nsresult
|
||||
nsMsgIdentity::getBoolPref(const char *prefname,
|
||||
PRBool *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultBoolPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultBoolPref(const char *prefname,
|
||||
PRBool *val) {
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setBoolPref(const char *prefname,
|
||||
PRBool val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->SetBoolPref(prefName, val);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getCharPref(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultCharPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultCharPref(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = nsnull; // null is ok to return here
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setCharPref(const char *prefname,
|
||||
const char *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_OK;
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
if (val)
|
||||
rv = m_prefs->SetCharPref(prefName, val);
|
||||
else
|
||||
m_prefs->ClearUserPref(prefName);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getIntPref(const char *prefname,
|
||||
PRInt32 *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultIntPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultIntPref(const char *prefname,
|
||||
PRInt32 *val) {
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = 0;
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setIntPref(const char *prefname,
|
||||
PRInt32 val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->SetIntPref(prefName, val);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::SetKey(const char* identityKey)
|
||||
{
|
||||
PR_FREEIF(m_identityKey);
|
||||
m_identityKey = PL_strdup(identityKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::GetIdentityName(char **idName) {
|
||||
if (!idName) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*idName = nsnull;
|
||||
nsresult rv = getCharPref("identityName",idName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// there's probably a better way of doing this
|
||||
// thats unicode friendly?
|
||||
if (!(*idName)) {
|
||||
nsXPIDLCString fullName;
|
||||
rv = GetFullName(getter_Copies(fullName));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLCString email;
|
||||
rv = GetEmail(getter_Copies(email));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*idName = PR_smprintf("%s <%s>", (const char*)fullName,
|
||||
(const char*)email);
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgIdentity::SetIdentityName(const char *idName) {
|
||||
return setCharPref("identityName", idName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::ToString(PRUnichar **aResult)
|
||||
{
|
||||
nsString idname("[nsIMsgIdentity: ");
|
||||
idname += m_identityKey;
|
||||
idname += "]";
|
||||
|
||||
*aResult = idname.ToNewUnicode();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Identity attribute accessors */
|
||||
|
||||
// XXX - these are a COM objects, use NS_ADDREF
|
||||
//NS_IMPL_GETSET(nsMsgIdentity, Signature, nsIMsgSignature*, m_signature);
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::GetSignature(nsIFileSpec **sig) {
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, "sig_file");
|
||||
rv = m_prefs->GetFilePref(prefName, sig);
|
||||
if (NS_FAILED(rv))
|
||||
*sig = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::SetSignature(nsIFileSpec *sig)
|
||||
{
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_OK;
|
||||
char *prefName = getPrefName(m_identityKey, "sig_file");
|
||||
if (sig)
|
||||
rv = m_prefs->SetFilePref(NS_CONST_CAST(const char*,prefName), sig,
|
||||
PR_FALSE);
|
||||
/*
|
||||
else
|
||||
m_prefs->ClearFilePref(prefName);
|
||||
*/
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_GETSET(nsMsgIdentity, VCard, nsIMsgVCard*, m_vCard);
|
||||
|
||||
NS_IMPL_GETTER_STR(nsMsgIdentity::GetKey, m_identityKey);
|
||||
|
||||
NS_IMPL_IDPREF_STR(FullName, "fullName");
|
||||
NS_IMPL_IDPREF_STR(Email, "useremail");
|
||||
NS_IMPL_IDPREF_STR(ReplyTo, "reply_to");
|
||||
NS_IMPL_IDPREF_STR(Organization, "organization");
|
||||
NS_IMPL_IDPREF_BOOL(ComposeHtml, "compose_html");
|
||||
NS_IMPL_IDPREF_BOOL(AttachVCard, "attach_vcard");
|
||||
NS_IMPL_IDPREF_BOOL(AttachSignature, "attach_signature");
|
||||
|
||||
NS_IMPL_IDPREF_BOOL(DoFcc, "fcc");
|
||||
NS_IMPL_IDPREF_STR(FccFolder, "fcc_folder");
|
||||
|
||||
NS_IMPL_IDPREF_BOOL(BccSelf, "bcc_self");
|
||||
NS_IMPL_IDPREF_BOOL(BccOthers, "bcc_other");
|
||||
NS_IMPL_IDPREF_STR (BccList, "bcc_other_list");
|
||||
|
||||
NS_IMPL_IDPREF_STR (DraftFolder, "draft_folder");
|
||||
NS_IMPL_IDPREF_STR (StationaryFolder, "stationary_folder");
|
||||
NS_IMPL_IDPREF_STR (JunkMailFolder, "spam_folder");
|
||||
|
||||
|
||||
110
mozilla/mailnews/base/util/nsMsgIdentity.h
Normal file
110
mozilla/mailnews/base/util/nsMsgIdentity.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgIdentity_h___
|
||||
#define nsMsgIdentity_h___
|
||||
|
||||
#include "nsIMsgIdentity.h"
|
||||
#include "nsIPref.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// an identity is an object designed to encapsulate all the information we need
|
||||
// to know about a user identity. I expect this interface to grow and change a lot
|
||||
// as we flesh out our thoughts on multiple identities and what properties go into
|
||||
// these identities.
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMsgIdentity : public nsIMsgIdentity,
|
||||
public nsIShutdownListener
|
||||
{
|
||||
public:
|
||||
nsMsgIdentity();
|
||||
virtual ~nsMsgIdentity();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGIDENTITY
|
||||
|
||||
// nsIShutdownListener
|
||||
|
||||
NS_IMETHOD OnShutdown(const nsCID& aClass, nsISupports *service);
|
||||
|
||||
private:
|
||||
nsIMsgSignature* m_signature;
|
||||
nsIMsgVCard* m_vCard;
|
||||
char *m_identityKey;
|
||||
nsIPref *m_prefs;
|
||||
|
||||
protected:
|
||||
nsresult getPrefService();
|
||||
char *getPrefName(const char *identityKey, const char *pref);
|
||||
char *getDefaultPrefName(const char *pref);
|
||||
nsresult getCharPref(const char *pref, char **);
|
||||
nsresult getDefaultCharPref(const char *pref, char **);
|
||||
nsresult setCharPref(const char *pref, const char *);
|
||||
|
||||
nsresult getBoolPref(const char *pref, PRBool *);
|
||||
nsresult getDefaultBoolPref(const char *pref, PRBool *);
|
||||
nsresult setBoolPref(const char *pref, PRBool);
|
||||
|
||||
nsresult getIntPref(const char *pref, PRInt32 *);
|
||||
nsresult getDefaultIntPref(const char *pref, PRInt32 *);
|
||||
nsresult setIntPref(const char *pref, PRInt32);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define NS_IMPL_IDPREF_STR(_postfix, _prefname) \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(char **retval) \
|
||||
{ \
|
||||
return getCharPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(const char *value) \
|
||||
{ \
|
||||
return setCharPref(_prefname, value);\
|
||||
}
|
||||
|
||||
#define NS_IMPL_IDPREF_BOOL(_postfix, _prefname)\
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(PRBool *retval) \
|
||||
{ \
|
||||
return getBoolPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(PRBool value) \
|
||||
{ \
|
||||
return setBoolPref(_prefname, value); \
|
||||
}
|
||||
|
||||
#define NS_IMPL_IDPREF_INT(_postfix, _prefname) \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(PRInt32 *retval) \
|
||||
{ \
|
||||
return getIntPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(PRInt32 value) \
|
||||
{ \
|
||||
return setIntPref(_prefname, value); \
|
||||
}
|
||||
|
||||
|
||||
#endif /* nsMsgIdentity_h___ */
|
||||
603
mozilla/mailnews/base/util/nsMsgIncomingServer.cpp
Normal file
603
mozilla/mailnews/base/util/nsMsgIncomingServer.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsMsgIncomingServer.h"
|
||||
#include "nscore.h"
|
||||
#include "nsCom.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgFolderCache.h"
|
||||
#include "nsIMsgFolderCacheElement.h"
|
||||
#include "nsINetSupportDialogService.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIMsgProtocolInfo.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgIncomingServer);
|
||||
|
||||
nsMsgIncomingServer::nsMsgIncomingServer():
|
||||
m_prefs(0),
|
||||
m_serverKey(0),
|
||||
m_rootFolder(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgIncomingServer);
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
m_serverBusy = PR_FALSE;
|
||||
m_password = "";
|
||||
}
|
||||
|
||||
nsMsgIncomingServer::~nsMsgIncomingServer()
|
||||
{
|
||||
|
||||
MOZ_COUNT_DTOR(nsMsgIncomingServer);
|
||||
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID,
|
||||
m_prefs,
|
||||
nsnull);
|
||||
PR_FREEIF(m_serverKey)
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMsgIncomingServer, nsIMsgIncomingServer)
|
||||
|
||||
NS_IMPL_GETSET(nsMsgIncomingServer, ServerBusy, PRBool, m_serverBusy)
|
||||
NS_IMPL_GETTER_STR(nsMsgIncomingServer::GetKey, m_serverKey)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetKey(const char * serverKey)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// in order to actually make use of the key, we need the prefs
|
||||
if (!m_prefs)
|
||||
rv = nsServiceManager::GetService(kPrefServiceCID,
|
||||
nsCOMTypeInfo<nsIPref>::GetIID(),
|
||||
(nsISupports**)&m_prefs);
|
||||
|
||||
PR_FREEIF(m_serverKey);
|
||||
m_serverKey = PL_strdup(serverKey);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetRootFolder(nsIFolder * aRootFolder)
|
||||
{
|
||||
m_rootFolder = aRootFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetRootFolder(nsIFolder * *aRootFolder)
|
||||
{
|
||||
if (!aRootFolder)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (m_rootFolder) {
|
||||
*aRootFolder = m_rootFolder;
|
||||
NS_ADDREF(*aRootFolder);
|
||||
} else {
|
||||
nsresult rv = CreateRootFolder();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aRootFolder = m_rootFolder;
|
||||
NS_IF_ADDREF(*aRootFolder);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::PerformBiff()
|
||||
{
|
||||
//This had to be implemented in the derived class, but in case someone doesn't implement it
|
||||
//just return not implemented.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (m_rootFolder)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryInterface(m_rootFolder, &rv);
|
||||
if (NS_SUCCEEDED(rv) && msgFolder)
|
||||
rv = msgFolder->WriteToFolderCache(folderCache);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::CloseCachedConnections()
|
||||
{
|
||||
// derived class should override if they cache connections.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetServerURI(char **)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::CreateRootFolder()
|
||||
{
|
||||
nsresult rv;
|
||||
// get the URI from the incoming server
|
||||
nsXPIDLCString serverUri;
|
||||
rv = GetServerURI(getter_Copies(serverUri));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIRDFService, rdf,
|
||||
kRDFServiceCID, &rv);
|
||||
|
||||
// get the corresponding RDF resource
|
||||
// RDF will create the server resource if it doesn't already exist
|
||||
nsCOMPtr<nsIRDFResource> serverResource;
|
||||
rv = rdf->GetResource(serverUri, getter_AddRefs(serverResource));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// make incoming server know about its root server folder so we
|
||||
// can find sub-folders given an incoming server.
|
||||
m_rootFolder = do_QueryInterface(serverResource, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *
|
||||
nsMsgIncomingServer::getPrefName(const char *serverKey,
|
||||
const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.server.%s.%s", serverKey, fullPrefName);
|
||||
}
|
||||
|
||||
// this will be slightly faster than the above, and allows
|
||||
// the "default" server preference root to be set in one place
|
||||
char *
|
||||
nsMsgIncomingServer::getDefaultPrefName(const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.server.default.%s", fullPrefName);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetBoolValue(const char *prefname,
|
||||
PRBool *val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultBoolPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultBoolPref(const char *prefname,
|
||||
PRBool *val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetBoolValue(const char *prefname,
|
||||
PRBool val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
PRBool defaultValue;
|
||||
rv = getDefaultBoolPref(prefname, &defaultValue);
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
val == defaultValue)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetBoolPref(fullPrefName, val);
|
||||
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetIntValue(const char *prefname,
|
||||
PRInt32 *val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultIntPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetFileValue(const char* prefname,
|
||||
nsIFileSpec **spec)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetFilePref(fullPrefName, spec);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetFileValue(const char* prefname,
|
||||
nsIFileSpec *spec)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->SetFilePref(fullPrefName, spec, PR_FALSE);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultIntPref(const char *prefname,
|
||||
PRInt32 *val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = 0;
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetIntValue(const char *prefname,
|
||||
PRInt32 val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
PRInt32 defaultVal;
|
||||
rv = getDefaultIntPref(prefname, &defaultVal);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && defaultVal == val)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetIntPref(fullPrefName, val);
|
||||
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetCharValue(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultCharPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultCharPref(const char *prefname,
|
||||
char **val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = nsnull; // null is ok to return here
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetCharValue(const char *prefname,
|
||||
const char * val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
if (!val) {
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char *defaultVal=nsnull;
|
||||
rv = getDefaultCharPref(prefname, &defaultVal);
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
PL_strcmp(defaultVal, val) == 0)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetCharPref(fullPrefName, val);
|
||||
|
||||
PR_FREEIF(defaultVal);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// pretty name is the display name to show to the user
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetPrettyName(PRUnichar **retval) {
|
||||
|
||||
char *val=nsnull;
|
||||
nsresult rv = GetCharValue("name", &val);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsString prettyName;
|
||||
|
||||
// if there's no name, then just return the hostname
|
||||
if (val) {
|
||||
prettyName = val;
|
||||
} else {
|
||||
|
||||
nsXPIDLCString username;
|
||||
rv = GetUsername(getter_Copies(username));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if ((const char*)username &&
|
||||
PL_strcmp((const char*)username, "")!=0) {
|
||||
prettyName = username;
|
||||
prettyName += " on ";
|
||||
}
|
||||
|
||||
nsXPIDLCString hostname;
|
||||
rv = GetHostName(getter_Copies(hostname));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
prettyName += hostname;
|
||||
}
|
||||
|
||||
*retval = prettyName.ToNewUnicode();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetPrettyName(const PRUnichar *value) {
|
||||
// this is lossy. Not sure what to do.
|
||||
nsCString str(value);
|
||||
return SetCharValue("name", str.GetBuffer());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::ToString(PRUnichar** aResult) {
|
||||
nsString servername("[nsIMsgIncomingServer: ");
|
||||
servername += m_serverKey;
|
||||
servername += "]";
|
||||
|
||||
*aResult = servername.ToNewUnicode();
|
||||
NS_ASSERTION(*aResult, "no server name!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::SetPassword(const char * aPassword)
|
||||
{
|
||||
// if remember password is turned on, write the password to preferences
|
||||
// otherwise, just set the password so we remember it for the rest of the current
|
||||
// session.
|
||||
|
||||
PRBool rememberPassword = PR_FALSE;
|
||||
GetRememberPassword(&rememberPassword);
|
||||
|
||||
if (rememberPassword)
|
||||
{
|
||||
SetPrefPassword((char *) aPassword);
|
||||
}
|
||||
|
||||
m_password = aPassword;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::GetPassword(char ** aPassword)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool rememberPassword = PR_FALSE;
|
||||
// okay, here's the scoop for this messs...
|
||||
// (1) if we have a password already, go ahead and use it!
|
||||
// (2) if remember password is turned on, try reading in from the prefs and if we have one, go ahead
|
||||
// and use it
|
||||
// (3) otherwise prompt the user for a password and then remember that password in the server
|
||||
|
||||
if (m_password.IsEmpty())
|
||||
{
|
||||
|
||||
// case (2)
|
||||
GetRememberPassword(&rememberPassword);
|
||||
if (rememberPassword)
|
||||
{
|
||||
nsXPIDLCString password;
|
||||
GetPrefPassword(getter_Copies(password));
|
||||
m_password = password;
|
||||
}
|
||||
}
|
||||
|
||||
*aPassword = m_password.ToNewCString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetPasswordWithUI(const PRUnichar * aPromptMessage, char **aPassword)
|
||||
{
|
||||
|
||||
nsXPIDLCString prefvalue;
|
||||
GetPassword(getter_Copies(prefvalue));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (m_password.IsEmpty()) {
|
||||
// prompt the user for the password
|
||||
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
PRUnichar * uniPassword;
|
||||
PRBool okayValue = PR_TRUE;
|
||||
dialog->PromptPassword(aPromptMessage, &uniPassword, &okayValue);
|
||||
|
||||
if (!okayValue) // if the user pressed cancel, just return NULL;
|
||||
{
|
||||
*aPassword = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// we got a password back...so remember it
|
||||
nsCString aCStr(uniPassword);
|
||||
|
||||
SetPassword((const char *) aCStr);
|
||||
} // if we got a prompt dialog
|
||||
} // if the password is empty
|
||||
|
||||
*aPassword = m_password.ToNewCString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetDefaultLocalPath(nsIFileSpec *aDefaultLocalPath)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString type;
|
||||
GetType(getter_Copies(type));
|
||||
|
||||
nsCAutoString progid(NS_MSGPROTOCOLINFO_PROGID_PREFIX);
|
||||
progid += type;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgProtocolInfo, protocolInfo, progid, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = protocolInfo->SetDefaultLocalPath(aDefaultLocalPath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetLocalPath(nsIFileSpec **aLocalPath)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// if the local path has already been set, use it
|
||||
rv = GetFileValue("directory", aLocalPath);
|
||||
if (NS_SUCCEEDED(rv) && *aLocalPath) return rv;
|
||||
|
||||
// otherwise, create the path using. note we are using the
|
||||
// server key instead of the hostname
|
||||
//
|
||||
// TODO: handle the case where they migrated a server of hostname "server4"
|
||||
// and we create a server (with the account wizard) with key "server4"
|
||||
// we'd get a collision.
|
||||
// need to modify the code that creates keys to check for disk collision
|
||||
nsXPIDLCString type;
|
||||
GetType(getter_Copies(type));
|
||||
|
||||
nsCAutoString progid(NS_MSGPROTOCOLINFO_PROGID_PREFIX);
|
||||
progid += type;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgProtocolInfo, protocolInfo, progid, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> path;
|
||||
rv = protocolInfo->GetDefaultLocalPath(getter_AddRefs(path));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
path->CreateDir();
|
||||
|
||||
nsXPIDLCString key;
|
||||
rv = GetKey(getter_Copies(key));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = path->AppendRelativeUnixPath(key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = SetLocalPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aLocalPath = path;
|
||||
NS_ADDREF(*aLocalPath);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetLocalPath(nsIFileSpec *spec)
|
||||
{
|
||||
if (spec) {
|
||||
spec->CreateDir();
|
||||
return SetFileValue("directory", spec);
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetRememberPassword(PRBool value)
|
||||
{
|
||||
if (value)
|
||||
SetPrefPassword(m_password);
|
||||
else
|
||||
SetPrefPassword(nsnull);
|
||||
return SetBoolValue("remember_password", value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetRememberPassword(PRBool* value)
|
||||
{
|
||||
return GetBoolValue("remember_password", value);
|
||||
}
|
||||
|
||||
// use the convenience macros to implement the accessors
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, HostName, "hostname");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Username, "userName");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, PrefPassword, "password");
|
||||
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DoBiff, "check_new_mail");
|
||||
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, BiffMinutes, "check_time");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Type, "type");
|
||||
|
||||
/* what was this called in 4.x? */
|
||||
// pref("mail.pop3_gets_new_mail", true);
|
||||
|
||||
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DownloadOnBiff, "download_on_biff");
|
||||
70
mozilla/mailnews/base/util/nsMsgIncomingServer.h
Normal file
70
mozilla/mailnews/base/util/nsMsgIncomingServer.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgIncomingServer_h__
|
||||
#define nsMsgIncomingServer_h__
|
||||
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsIPref.h"
|
||||
#include "msgCore.h"
|
||||
#include "nsIFolder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIMsgFolderCache;
|
||||
|
||||
/*
|
||||
* base class for nsIMsgIncomingServer - derive your class from here
|
||||
* if you want to get some free implementation
|
||||
*
|
||||
* this particular implementation is not meant to be used directly.
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgIncomingServer : public nsIMsgIncomingServer {
|
||||
public:
|
||||
nsMsgIncomingServer();
|
||||
virtual ~nsMsgIncomingServer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIMSGINCOMINGSERVER
|
||||
|
||||
private:
|
||||
nsIPref *m_prefs;
|
||||
char *m_serverKey;
|
||||
nsCString m_password;
|
||||
PRBool m_serverBusy;
|
||||
|
||||
protected:
|
||||
char *getPrefName(const char *serverKey, const char *pref);
|
||||
char *getDefaultPrefName(const char *pref);
|
||||
|
||||
// these are private pref getters and setters for the password
|
||||
// field. Callers should be using Get/Set Password
|
||||
NS_IMETHOD GetPrefPassword(char * *aPassword);
|
||||
NS_IMETHOD SetPrefPassword(const char * aPassword);
|
||||
|
||||
nsCOMPtr <nsIFolder> m_rootFolder;
|
||||
nsresult getDefaultCharPref(const char *pref, char **);
|
||||
nsresult getDefaultBoolPref(const char *pref, PRBool *);
|
||||
nsresult getDefaultIntPref(const char *pref, PRInt32 *);
|
||||
|
||||
nsresult CreateRootFolder();
|
||||
|
||||
};
|
||||
|
||||
#endif // nsMsgIncomingServer_h__
|
||||
1471
mozilla/mailnews/base/util/nsMsgKeySet.cpp
Normal file
1471
mozilla/mailnews/base/util/nsMsgKeySet.cpp
Normal file
File diff suppressed because it is too large
Load Diff
115
mozilla/mailnews/base/util/nsMsgKeySet.h
Normal file
115
mozilla/mailnews/base/util/nsMsgKeySet.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsMsgKeySet_H_
|
||||
#define _nsMsgKeySet_H_
|
||||
|
||||
#include "msgCore.h"
|
||||
|
||||
// nsMsgKeySet represents a set of articles. Typically, it is the set of
|
||||
// read articles from a .newsrc file, but it can be used for other purposes
|
||||
// too.
|
||||
|
||||
#if 0
|
||||
// If a MSG_NewsHost* is supplied to the creation routine, then that
|
||||
// MSG_NewsHost will be notified whenever a change is made to set.
|
||||
class MSG_NewsHost;
|
||||
#endif
|
||||
|
||||
class NS_MSG_BASE nsMsgKeySet {
|
||||
public:
|
||||
// Creates an empty set.
|
||||
static nsMsgKeySet* Create(/* MSG_NewsHost* host = NULL*/);
|
||||
|
||||
// Creates a set from the list of numbers, as might be found in a
|
||||
// newsrc file.
|
||||
static nsMsgKeySet* Create(const char* str/* , MSG_NewsHost* host = NULL*/);
|
||||
~nsMsgKeySet();
|
||||
|
||||
// FirstNonMember() returns the lowest non-member of the set that is
|
||||
// greater than 0.
|
||||
PRInt32 FirstNonMember();
|
||||
|
||||
// Output() converts to a string representation suitable for writing to a
|
||||
// .newsrc file. (The result must be freed by the caller using delete[].)
|
||||
char* Output();
|
||||
|
||||
// IsMember() returns whether the given article is a member of this set.
|
||||
PRBool IsMember(PRInt32 art);
|
||||
|
||||
// Add() adds the given article to the set. (Returns 1 if a change was
|
||||
// made, 0 if it was already there, and negative on error.)
|
||||
int Add(PRInt32 art);
|
||||
|
||||
// Remove() removes the given article from the set.
|
||||
int Remove(PRInt32 art);
|
||||
|
||||
// AddRange() adds the (inclusive) given range of articles to the set.
|
||||
int AddRange(PRInt32 first, PRInt32 last);
|
||||
|
||||
// CountMissingInRange() takes an inclusive range of articles and returns
|
||||
// the number of articles in that range which are not in the set.
|
||||
PRInt32 CountMissingInRange(PRInt32 start, PRInt32 end);
|
||||
|
||||
// FirstMissingRange() takes an inclusive range and finds the first range
|
||||
// of articles that are not in the set. If none, return zeros.
|
||||
int FirstMissingRange(PRInt32 min, PRInt32 max, PRInt32* first, PRInt32* last);
|
||||
|
||||
|
||||
// LastMissingRange() takes an inclusive range and finds the last range
|
||||
// of articles that are not in the set. If none, return zeros.
|
||||
int LastMissingRange(PRInt32 min, PRInt32 max, PRInt32* first, PRInt32* last);
|
||||
|
||||
PRInt32 GetLastMember();
|
||||
PRInt32 GetFirstMember();
|
||||
void SetLastMember(PRInt32 highWaterMark);
|
||||
// For debugging only...
|
||||
PRInt32 getLength() {return m_length;}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void RunTests();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
nsMsgKeySet(/* MSG_NewsHost* host */);
|
||||
nsMsgKeySet(const char* /* , MSG_NewsHost* host */);
|
||||
PRBool Grow();
|
||||
PRBool Optimize();
|
||||
|
||||
#ifdef DEBUG
|
||||
static void test_decoder(const char*);
|
||||
static void test_adder();
|
||||
static void test_ranges();
|
||||
static void test_member(PRBool with_cache);
|
||||
#endif
|
||||
|
||||
PRInt32 *m_data; /* the numbers composing the `chunks' */
|
||||
PRInt32 m_data_size; /* size of that malloc'ed block */
|
||||
PRInt32 m_length; /* active area */
|
||||
|
||||
PRInt32 m_cached_value; /* a potential set member, or -1 if unset*/
|
||||
PRInt32 m_cached_value_index; /* the index into `data' at which a search
|
||||
to determine whether `cached_value' was
|
||||
a member of the set ended. */
|
||||
#ifdef NEWSRC_DOES_HOST_STUFF
|
||||
MSG_NewsHost* m_host;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsMsgKeySet_H_ */
|
||||
384
mozilla/mailnews/base/util/nsMsgLineBuffer.cpp
Normal file
384
mozilla/mailnews/base/util/nsMsgLineBuffer.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "prlog.h"
|
||||
#include "nsMsgLineBuffer.h"
|
||||
|
||||
#include "nsIInputStream.h" // used by nsMsgLineStreamBuffer
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsByteArray);
|
||||
|
||||
nsByteArray::nsByteArray()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsByteArray);
|
||||
m_buffer = NULL;
|
||||
m_bufferSize = 0;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
|
||||
nsByteArray::~nsByteArray()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsByteArray);
|
||||
PR_FREEIF(m_buffer);
|
||||
}
|
||||
|
||||
nsresult nsByteArray::GrowBuffer(PRUint32 desired_size, PRUint32 quantum)
|
||||
{
|
||||
if (m_bufferSize < desired_size)
|
||||
{
|
||||
char *new_buf;
|
||||
PRUint32 increment = desired_size - m_bufferSize;
|
||||
if (increment < quantum) /* always grow by a minimum of N bytes */
|
||||
increment = quantum;
|
||||
|
||||
|
||||
new_buf = (m_buffer
|
||||
? (char *) PR_REALLOC (m_buffer, (m_bufferSize + increment))
|
||||
: (char *) PR_MALLOC (m_bufferSize + increment));
|
||||
if (! new_buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
m_buffer = new_buf;
|
||||
m_bufferSize += increment;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult nsByteArray::AppendString(const char *string)
|
||||
{
|
||||
PRUint32 strLength = (string) ? PL_strlen(string) : 0;
|
||||
return AppendBuffer(string, strLength);
|
||||
|
||||
}
|
||||
|
||||
nsresult nsByteArray::AppendBuffer(const char *buffer, PRUint32 length)
|
||||
{
|
||||
nsresult ret = NS_OK;
|
||||
if (m_bufferPos + length > m_bufferSize)
|
||||
ret = GrowBuffer(m_bufferPos + length, 1024);
|
||||
if (ret == NS_OK)
|
||||
{
|
||||
memcpy(m_buffer + m_bufferPos, buffer, length);
|
||||
m_bufferPos += length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgLineBuffer);
|
||||
|
||||
nsMsgLineBuffer::nsMsgLineBuffer(nsMsgLineBufferHandler *handler, PRBool convertNewlinesP)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgLineBuffer);
|
||||
m_handler = handler;
|
||||
m_convertNewlinesP = convertNewlinesP;
|
||||
m_lookingForCRLF = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMsgLineBuffer::~nsMsgLineBuffer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsMsgLineBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
nsMsgLineBuffer::SetLookingForCRLF(PRBool b)
|
||||
{
|
||||
m_lookingForCRLF = b;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::BufferInput(const char *net_buffer, PRInt32 net_buffer_size)
|
||||
{
|
||||
int status = 0;
|
||||
if (m_bufferPos > 0 && m_buffer && m_buffer[m_bufferPos - 1] == CR &&
|
||||
net_buffer_size > 0 && net_buffer[0] != LF) {
|
||||
/* The last buffer ended with a CR. The new buffer does not start
|
||||
with a LF. This old buffer should be shipped out and discarded. */
|
||||
PR_ASSERT(m_bufferSize > m_bufferPos);
|
||||
if (m_bufferSize <= m_bufferPos) return -1;
|
||||
status = ConvertAndSendBuffer();
|
||||
if (status < 0)
|
||||
return status;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
while (net_buffer_size > 0)
|
||||
{
|
||||
const char *net_buffer_end = net_buffer + net_buffer_size;
|
||||
const char *newline = 0;
|
||||
const char *s;
|
||||
|
||||
|
||||
for (s = net_buffer; s < net_buffer_end; s++)
|
||||
{
|
||||
if (m_lookingForCRLF) {
|
||||
/* Move forward in the buffer until the first newline.
|
||||
Stop when we see CRLF, CR, or LF, or the end of the buffer.
|
||||
*But*, if we see a lone CR at the *very end* of the buffer,
|
||||
treat this as if we had reached the end of the buffer without
|
||||
seeing a line terminator. This is to catch the case of the
|
||||
buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n".
|
||||
*/
|
||||
if (*s == CR || *s == LF) {
|
||||
newline = s;
|
||||
if (newline[0] == CR) {
|
||||
if (s == net_buffer_end - 1) {
|
||||
/* CR at end - wait for the next character. */
|
||||
newline = 0;
|
||||
break;
|
||||
}
|
||||
else if (newline[1] == LF) {
|
||||
/* CRLF seen; swallow both. */
|
||||
newline++;
|
||||
}
|
||||
}
|
||||
newline++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* if not looking for a CRLF, stop at CR or LF. (for example, when parsing the newsrc file). this fixes #9896, where we'd lose the last line of anything we'd parse that used CR as the line break. */
|
||||
if (*s == CR || *s == LF) {
|
||||
newline = s;
|
||||
newline++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure room in the net_buffer and append some or all of the current
|
||||
chunk of data to it. */
|
||||
{
|
||||
const char *end = (newline ? newline : net_buffer_end);
|
||||
PRUint32 desired_size = (end - net_buffer) + m_bufferPos + 1;
|
||||
|
||||
if (desired_size >= m_bufferSize)
|
||||
{
|
||||
status = GrowBuffer (desired_size, 1024);
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
memcpy (m_buffer + m_bufferPos, net_buffer, (end - net_buffer));
|
||||
m_bufferPos += (end - net_buffer);
|
||||
}
|
||||
|
||||
/* Now m_buffer contains either a complete line, or as complete
|
||||
a line as we have read so far.
|
||||
|
||||
If we have a line, process it, and then remove it from `m_buffer'.
|
||||
Then go around the loop again, until we drain the incoming data.
|
||||
*/
|
||||
if (!newline)
|
||||
return 0;
|
||||
|
||||
status = ConvertAndSendBuffer();
|
||||
if (status < 0) return status;
|
||||
|
||||
net_buffer_size -= (newline - net_buffer);
|
||||
net_buffer = newline;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
#ifdef DEBUG_bienvenu
|
||||
printf("returning from buffer input m_bufferPos = %ld\n", m_bufferPos);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::HandleLine(char *line, PRUint32 line_length)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "must override this method if you don't provide a handler");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::ConvertAndSendBuffer()
|
||||
{
|
||||
/* Convert the line terminator to the native form.
|
||||
*/
|
||||
|
||||
char *buf = m_buffer;
|
||||
PRInt32 length = m_bufferPos;
|
||||
|
||||
char* newline;
|
||||
|
||||
PR_ASSERT(buf && length > 0);
|
||||
if (!buf || length <= 0)
|
||||
return -1;
|
||||
newline = buf + length;
|
||||
|
||||
PR_ASSERT(newline[-1] == CR || newline[-1] == LF);
|
||||
if (newline[-1] != CR && newline[-1] != LF)
|
||||
return -1;
|
||||
|
||||
if (!m_convertNewlinesP)
|
||||
{
|
||||
}
|
||||
#if (MSG_LINEBREAK_LEN == 1)
|
||||
else if ((newline - buf) >= 2 &&
|
||||
newline[-2] == CR &&
|
||||
newline[-1] == LF)
|
||||
{
|
||||
/* CRLF -> CR or LF */
|
||||
buf [length - 2] = MSG_LINEBREAK[0];
|
||||
length--;
|
||||
}
|
||||
else if (newline > buf + 1 &&
|
||||
newline[-1] != MSG_LINEBREAK[0])
|
||||
{
|
||||
/* CR -> LF or LF -> CR */
|
||||
buf [length - 1] = MSG_LINEBREAK[0];
|
||||
}
|
||||
#else
|
||||
else if (((newline - buf) >= 2 && newline[-2] != CR) ||
|
||||
((newline - buf) >= 1 && newline[-1] != LF))
|
||||
{
|
||||
/* LF -> CRLF or CR -> CRLF */
|
||||
length++;
|
||||
buf[length - 2] = MSG_LINEBREAK[0];
|
||||
buf[length - 1] = MSG_LINEBREAK[1];
|
||||
}
|
||||
#endif
|
||||
|
||||
return (m_handler) ? m_handler->HandleLine(buf, length) : HandleLine(buf, length);
|
||||
}
|
||||
|
||||
// If there's still some data (non CRLF terminated) flush it out
|
||||
PRInt32 nsMsgLineBuffer::FlushLastLine()
|
||||
{
|
||||
char *buf = m_buffer + m_bufferPos;
|
||||
PRInt32 length = m_bufferPos - 1;
|
||||
if (length > 0)
|
||||
return (m_handler) ? m_handler->HandleLine(buf, length) : HandleLine(buf, length);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is a utility class used to efficiently extract lines from an input stream by buffering
|
||||
// read but unprocessed stream data in a buffer.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsMsgLineStreamBuffer::nsMsgLineStreamBuffer(PRUint32 aBufferSize, const char * aEndOfLineToken,
|
||||
PRBool aAllocateNewLines, PRBool aEatCRLFs)
|
||||
: m_eatCRLFs(aEatCRLFs), m_allocateNewLines(aAllocateNewLines),
|
||||
m_endOfLineToken(aEndOfLineToken)
|
||||
{
|
||||
NS_PRECONDITION(aBufferSize > 0, "invalid buffer size!!!");
|
||||
m_dataBuffer = nsnull;
|
||||
m_startPos = nsnull;
|
||||
|
||||
// used to buffer incoming data by ReadNextLineFromInput
|
||||
if (aBufferSize > 0)
|
||||
{
|
||||
m_dataBuffer = (char *) PR_CALLOC(sizeof(char) * aBufferSize);
|
||||
m_startPos = m_dataBuffer;
|
||||
}
|
||||
|
||||
m_dataBufferSize = aBufferSize;
|
||||
}
|
||||
|
||||
nsMsgLineStreamBuffer::~nsMsgLineStreamBuffer()
|
||||
{
|
||||
PR_FREEIF(m_dataBuffer); // release our buffer...
|
||||
}
|
||||
|
||||
// the design for this method has an inherit bug: if the length of the line is greater than the size of m_dataBufferSize,
|
||||
// then we'll never find the next line because we can't hold the whole line in memory.
|
||||
// aInputStream - the input stream we want to read a line from
|
||||
// aPauseForMoreData is returned as PR_TRUE if the stream does not yet contain a line and we must wait for more
|
||||
// data to come into the stream.
|
||||
|
||||
// Note to people wishing to modify this function: Be *VERY CAREFUL* this is a critical function used by all of
|
||||
// our mail protocols including imap, nntp, and pop. If you screw it up, you could break a lot of stuff.....
|
||||
|
||||
char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint32 &aNumBytesInLine, PRBool &aPauseForMoreData)
|
||||
{
|
||||
// try to extract a line from m_inputBuffer. If we don't have an entire line,
|
||||
// then read more bytes out from the stream. If the stream is empty then wait
|
||||
// on the monitor for more data to come in.
|
||||
|
||||
NS_PRECONDITION(m_startPos && m_dataBufferSize > 0, "invalid input arguments for read next line from input");
|
||||
|
||||
// initialize out values
|
||||
aPauseForMoreData = PR_FALSE;
|
||||
aNumBytesInLine = 0;
|
||||
char * endOfLine = nsnull;
|
||||
|
||||
PRUint32 numBytesInBuffer = PL_strlen(m_startPos);
|
||||
|
||||
if (numBytesInBuffer > 0) // any data in our internal buffer?
|
||||
endOfLine = PL_strstr(m_startPos, m_endOfLineToken); // see if we already have a line ending...
|
||||
|
||||
// it's possible that we got here before the first time we receive data from the server
|
||||
// so aInputStream will be nsnull...
|
||||
if (!endOfLine && aInputStream) // get some more data from the server
|
||||
{
|
||||
PRUint32 numBytesInStream = 0;
|
||||
PRUint32 numBytesCopied = 0;
|
||||
aInputStream->Available(&numBytesInStream);
|
||||
// if the number of bytes we want to read from the stream, is greater than the number
|
||||
// of bytes left in our buffer, then we need to shift the start pos and its contents
|
||||
// down to the beginning of m_dataBuffer...
|
||||
PRUint32 numFreeBytesInBuffer = (m_dataBuffer + m_dataBufferSize) - (m_startPos + numBytesInBuffer);
|
||||
if (numBytesInStream >= numFreeBytesInBuffer)
|
||||
{
|
||||
nsCRT::memcpy(m_dataBuffer, m_startPos, numBytesInBuffer);
|
||||
m_dataBuffer[numBytesInBuffer] = '\0'; // make sure the end of the buffer is terminated
|
||||
m_startPos = m_dataBuffer; // update the new start position
|
||||
// update the number of free bytes in the buffer
|
||||
numFreeBytesInBuffer = m_dataBufferSize - numBytesInBuffer;
|
||||
}
|
||||
|
||||
PRUint32 numBytesToCopy = PR_MIN(numFreeBytesInBuffer - 1 /* leave one for a null terminator */, numBytesInStream);
|
||||
// read the data into the end of our data buffer
|
||||
if (numBytesToCopy > 0)
|
||||
{
|
||||
aInputStream->Read(m_startPos + numBytesInBuffer, numBytesToCopy, &numBytesCopied);
|
||||
m_startPos[numBytesInBuffer + numBytesCopied] = '\0';
|
||||
}
|
||||
|
||||
// okay, now that we've tried to read in more data from the stream, look for another end of line
|
||||
// character
|
||||
endOfLine = PL_strstr(m_startPos, m_endOfLineToken);
|
||||
|
||||
}
|
||||
|
||||
// okay, now check again for endOfLine.
|
||||
if (endOfLine)
|
||||
{
|
||||
if (!m_eatCRLFs)
|
||||
endOfLine += PL_strlen(m_endOfLineToken); // count for CRLF
|
||||
|
||||
// PR_CALLOC zeros out the allocated line
|
||||
char* newLine = (char*) PR_CALLOC(endOfLine-m_startPos+1);
|
||||
if (!newLine)
|
||||
return nsnull;
|
||||
|
||||
nsCRT::memcpy(newLine, m_startPos, endOfLine-m_startPos); // copy the string into the new line buffer
|
||||
aNumBytesInLine = endOfLine - m_startPos;
|
||||
|
||||
if (m_eatCRLFs)
|
||||
endOfLine += PL_strlen(m_endOfLineToken); // advance past CRLF if we haven't already done so...
|
||||
|
||||
// now we need to update the data buffer to go past the line we just read out.
|
||||
if (PL_strlen(endOfLine) <= 0) // if no more data in the buffer, then just zero out the buffer...
|
||||
m_startPos[0] = '\0';
|
||||
else // advance
|
||||
m_startPos = endOfLine; // move us up to the end of the line
|
||||
return newLine;
|
||||
}
|
||||
|
||||
aPauseForMoreData = PR_TRUE;
|
||||
return nsnull; // if we somehow got here. we don't have another line in the buffer yet...need to wait for more data...
|
||||
}
|
||||
113
mozilla/mailnews/base/util/nsMsgLineBuffer.h
Normal file
113
mozilla/mailnews/base/util/nsMsgLineBuffer.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef _nsMsgLineBuffer_H
|
||||
#define _nsMsgLineBuffer_H
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
|
||||
// I can't believe I have to have this stupid class, but I can't find
|
||||
// anything suitable (nsStrImpl might be, when its done). nsIByteBuffer
|
||||
// would do, if I had a stream for input, which I don't.
|
||||
|
||||
class NS_MSG_BASE nsByteArray
|
||||
{
|
||||
public:
|
||||
nsByteArray();
|
||||
virtual ~nsByteArray();
|
||||
PRUint32 GetSize() {return m_bufferSize;}
|
||||
PRUint32 GetBufferPos() {return m_bufferPos;}
|
||||
nsresult GrowBuffer(PRUint32 desired_size, PRUint32 quantum = 1024);
|
||||
nsresult AppendString(const char *string);
|
||||
nsresult AppendBuffer(const char *buffer, PRUint32 length);
|
||||
void ResetWritePos() {m_bufferPos = 0;}
|
||||
char *GetBuffer() {return m_buffer;}
|
||||
protected:
|
||||
char *m_buffer;
|
||||
PRUint32 m_bufferSize;
|
||||
PRUint32 m_bufferPos; // write Pos in m_buffer - where the next byte should go.
|
||||
};
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMsgLineBufferHandler : public nsByteArray
|
||||
{
|
||||
public:
|
||||
virtual PRInt32 HandleLine(char *line, PRUint32 line_length) = 0;
|
||||
};
|
||||
|
||||
class NS_MSG_BASE nsMsgLineBuffer : public nsByteArray
|
||||
{
|
||||
public:
|
||||
nsMsgLineBuffer(nsMsgLineBufferHandler *handler, PRBool convertNewlinesP);
|
||||
|
||||
virtual ~nsMsgLineBuffer();
|
||||
PRInt32 BufferInput(const char *net_buffer, PRInt32 net_buffer_size);
|
||||
// Not sure why anyone cares, by NNTPHost seems to want to know the buf pos.
|
||||
PRUint32 GetBufferPos() {return m_bufferPos;}
|
||||
|
||||
virtual PRInt32 HandleLine(char *line, PRUint32 line_length);
|
||||
// flush last line, though it won't be CRLF terminated.
|
||||
virtual PRInt32 FlushLastLine();
|
||||
protected:
|
||||
nsMsgLineBuffer(PRBool convertNewlinesP);
|
||||
|
||||
PRInt32 ConvertAndSendBuffer();
|
||||
void SetLookingForCRLF(PRBool b);
|
||||
|
||||
nsMsgLineBufferHandler *m_handler;
|
||||
PRBool m_convertNewlinesP;
|
||||
PRBool m_lookingForCRLF;
|
||||
};
|
||||
|
||||
// I'm adding this utility class here for lack of a better place. This utility class is similar to nsMsgLineBuffer
|
||||
// except it works from an input stream. It is geared towards efficiently parsing new lines out of a stream by storing
|
||||
// read but unprocessed bytes in a buffer. I envision the primary use of this to be our mail protocols such as imap, news and
|
||||
// pop which need to process line by line data being returned in the form of a proxied stream from the server.
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
class NS_MSG_BASE nsMsgLineStreamBuffer
|
||||
{
|
||||
public:
|
||||
// aBufferSize -- size of the buffer you want us to use for buffering stream data
|
||||
// aEndOfLinetoken -- The delimeter string to be used for determining the end of line. This
|
||||
// allows us to parse platform specific end of line endings by making it
|
||||
// a parameter.
|
||||
// aAllocateNewLines -- PR_TRUE if you want calls to ReadNextLine to allocate new memory for the line.
|
||||
// if false, the char * returned is just a ptr into the buffer. Subsequent calls to
|
||||
// ReadNextLine will alter the data so your ptr only has a life time of a per call.
|
||||
// aEatCRLFs -- PR_TRUE if you don't want to see the CRLFs on the lines returned by ReadNextLine.
|
||||
// PR_FALSE if you do want to see them.
|
||||
nsMsgLineStreamBuffer(PRUint32 aBufferSize, const char * aEndOfLineToken, PRBool aAllocateNewLines, PRBool aEatCRLFs = PR_TRUE); // specify the size of the buffer you want the class to use....
|
||||
virtual ~nsMsgLineStreamBuffer();
|
||||
|
||||
// Caller must free the line returned using PR_Free
|
||||
// aEndOfLinetoken -- delimeter used to denote the end of a line.
|
||||
// aNumBytesInLine -- The number of bytes in the line returned
|
||||
// aPauseForMoreData -- There is not enough data in the stream to make a line at this time...
|
||||
char * ReadNextLine(nsIInputStream * aInputStream, PRUint32 &anumBytesInLine, PRBool &aPauseForMoreData);
|
||||
protected:
|
||||
PRBool m_eatCRLFs;
|
||||
PRBool m_allocateNewLines;
|
||||
char * m_dataBuffer;
|
||||
char * m_startPos;
|
||||
const char * m_endOfLineToken;
|
||||
PRUint32 m_dataBufferSize;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
399
mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp
Normal file
399
mozilla/mailnews/base/util/nsMsgMailNewsUrl.cpp
Normal file
@@ -0,0 +1,399 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgMailNewsUrl.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgMailSession.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
static NS_DEFINE_CID(kUrlListenerManagerCID, NS_URLLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
||||
|
||||
nsMsgMailNewsUrl::nsMsgMailNewsUrl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
// nsIURI specific state
|
||||
m_errorMessage = nsnull;
|
||||
m_runningUrl = PR_FALSE;
|
||||
m_updatingFolder = PR_FALSE;
|
||||
|
||||
nsComponentManager::CreateInstance(kUrlListenerManagerCID, nsnull, nsCOMTypeInfo<nsIUrlListenerManager>::GetIID(), (void **) getter_AddRefs(m_urlListeners));
|
||||
nsComponentManager::CreateInstance(kStandardUrlCID, nsnull, nsCOMTypeInfo<nsIURL>::GetIID(), (void **) getter_AddRefs(m_baseURL));
|
||||
}
|
||||
|
||||
nsMsgMailNewsUrl::~nsMsgMailNewsUrl()
|
||||
{
|
||||
PR_FREEIF(m_errorMessage);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMsgMailNewsUrl);
|
||||
NS_IMPL_RELEASE(nsMsgMailNewsUrl);
|
||||
|
||||
nsresult nsMsgMailNewsUrl::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIURI>::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIURI*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIURL>::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIURL*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIMsgMailNewsUrl>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = (void *) ((nsIMsgMailNewsUrl*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = (void *) ((nsIMsgMailNewsUrl*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
#if defined(NS_DEBUG)
|
||||
/*
|
||||
* Check for the debug-only interface indicating thread-safety
|
||||
*/
|
||||
static NS_DEFINE_IID(kIsThreadsafeIID, NS_ISTHREADSAFE_IID);
|
||||
if (aIID.Equals(kIsThreadsafeIID)) {
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIMsgMailNewsUrl specific support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult nsMsgMailNewsUrl::GetUrlState(PRBool * aRunningUrl)
|
||||
{
|
||||
if (aRunningUrl)
|
||||
*aRunningUrl = m_runningUrl;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::SetUrlState(PRBool aRunningUrl, nsresult aExitCode)
|
||||
{
|
||||
m_runningUrl = aRunningUrl;
|
||||
nsCOMPtr <nsIMsgStatusFeedback> statusFeedback;
|
||||
|
||||
if (NS_SUCCEEDED(GetStatusFeedback(getter_AddRefs(statusFeedback))) && statusFeedback)
|
||||
{
|
||||
if (m_runningUrl)
|
||||
statusFeedback->StartMeteors();
|
||||
else
|
||||
{
|
||||
statusFeedback->ShowProgress(0);
|
||||
statusFeedback->StopMeteors();
|
||||
}
|
||||
}
|
||||
if (m_urlListeners)
|
||||
{
|
||||
if (m_runningUrl)
|
||||
{
|
||||
m_urlListeners->OnStartRunningUrl(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_urlListeners->OnStopRunningUrl(this, aExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::RegisterListener (nsIUrlListener * aUrlListener)
|
||||
{
|
||||
if (m_urlListeners)
|
||||
m_urlListeners->RegisterListener(aUrlListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::UnRegisterListener (nsIUrlListener * aUrlListener)
|
||||
{
|
||||
if (m_urlListeners)
|
||||
m_urlListeners->UnRegisterListener(aUrlListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::SetErrorMessage (const char * errorMessage)
|
||||
{
|
||||
// functionality has been moved to nsIMsgStatusFeedback
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::GetErrorMessage (char ** errorMessage)
|
||||
{
|
||||
// functionality has been moved to nsIMsgStatusFeedback
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetServer(nsIMsgIncomingServer ** aIncomingServer)
|
||||
{
|
||||
// mscott --> we could cache a copy of the server here....but if we did, we run
|
||||
// the risk of leaking the server if any single url gets leaked....of course that
|
||||
// shouldn't happen...but it could. so i'm going to look it up every time and
|
||||
// we can look at caching it later.
|
||||
|
||||
nsXPIDLCString host;
|
||||
nsXPIDLCString scheme;
|
||||
|
||||
nsresult rv = GetHost(getter_Copies(host));
|
||||
rv = GetScheme(getter_Copies(scheme));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, session, kMsgMailSessionCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = session->GetAccountManager(getter_AddRefs(accountManager));
|
||||
if(NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = accountManager->FindServer(GetUserName(),
|
||||
host,
|
||||
scheme,
|
||||
aIncomingServer);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetStatusFeedback(nsIMsgStatusFeedback *aMsgFeedback)
|
||||
{
|
||||
if (aMsgFeedback)
|
||||
m_statusFeedback = do_QueryInterface(aMsgFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetStatusFeedback(nsIMsgStatusFeedback **aMsgFeedback)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// note: it is okay to return a null status feedback and not return an error
|
||||
// it's possible the url really doesn't have status feedback
|
||||
if (!m_statusFeedback)
|
||||
{
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
mailSession->GetTemporaryMsgStatusFeedback(getter_AddRefs(m_statusFeedback));
|
||||
}
|
||||
if (aMsgFeedback)
|
||||
{
|
||||
*aMsgFeedback = m_statusFeedback;
|
||||
NS_IF_ADDREF(*aMsgFeedback);
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetUpdatingFolder(PRBool *aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aResult = m_updatingFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetUpdatingFolder(PRBool updatingFolder)
|
||||
{
|
||||
m_updatingFolder = updatingFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// End nsIMsgMailNewsUrl specific support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIURI support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetSpec(char * *aSpec)
|
||||
{
|
||||
return m_baseURL->GetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetSpec(const char * aSpec)
|
||||
{
|
||||
return m_baseURL->SetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetScheme(char * *aScheme)
|
||||
{
|
||||
return m_baseURL->GetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetScheme(const char * aScheme)
|
||||
{
|
||||
return m_baseURL->SetScheme(aScheme);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPreHost(char * *aPreHost)
|
||||
{
|
||||
return m_baseURL->GetPreHost(aPreHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPreHost(const char * aPreHost)
|
||||
{
|
||||
return m_baseURL->SetPreHost(aPreHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(char * *aHost)
|
||||
{
|
||||
return m_baseURL->GetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetHost(const char * aHost)
|
||||
{
|
||||
return m_baseURL->SetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPort(PRInt32 *aPort)
|
||||
{
|
||||
return m_baseURL->GetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPort(PRInt32 aPort)
|
||||
{
|
||||
return m_baseURL->SetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPath(char * *aPath)
|
||||
{
|
||||
return m_baseURL->GetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPath(const char * aPath)
|
||||
{
|
||||
return m_baseURL->SetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::Equals(nsIURI *other, PRBool *_retval)
|
||||
{
|
||||
return m_baseURL->Equals(other, _retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::Clone(nsIURI **_retval)
|
||||
{
|
||||
return m_baseURL->Clone(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetRelativePath(const char *i_RelativePath)
|
||||
{
|
||||
return m_baseURL->SetRelativePath(i_RelativePath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetDirectory(char * *aDirectory)
|
||||
{
|
||||
return m_baseURL->GetDirectory(aDirectory);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetDirectory(const char *aDirectory)
|
||||
{
|
||||
|
||||
return m_baseURL->SetDirectory(aDirectory);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileName(char * *aFileName)
|
||||
{
|
||||
return m_baseURL->GetFileName(aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileBaseName(char * *aFileBaseName)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileBaseName(const char * aFileBaseName)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileExtension(char * *aFileExtension)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileExtension(const char * aFileExtension)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileName(const char * aFileName)
|
||||
{
|
||||
return m_baseURL->SetFileName(aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetParam(char * *aParam)
|
||||
{
|
||||
return m_baseURL->GetParam(aParam);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetParam(const char *aParam)
|
||||
{
|
||||
return m_baseURL->SetParam(aParam);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetQuery(char * *aQuery)
|
||||
{
|
||||
return m_baseURL->GetQuery(aQuery);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetQuery(const char *aQuery)
|
||||
{
|
||||
return m_baseURL->SetQuery(aQuery);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetRef(char * *aRef)
|
||||
{
|
||||
return m_baseURL->GetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetRef(const char *aRef)
|
||||
{
|
||||
return m_baseURL->SetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFilePath(char **o_DirFile)
|
||||
{
|
||||
return m_baseURL->GetFilePath(o_DirFile);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFilePath(const char *i_DirFile)
|
||||
{
|
||||
return m_baseURL->SetFilePath(i_DirFile);
|
||||
}
|
||||
|
||||
66
mozilla/mailnews/base/util/nsMsgMailNewsUrl.h
Normal file
66
mozilla/mailnews/base/util/nsMsgMailNewsUrl.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgMailNewsUrl_h___
|
||||
#define nsMsgMailNewsUrl_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIUrlListener.h"
|
||||
#include "nsIUrlListenerManager.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Okay, I found that all of the mail and news url interfaces needed to support
|
||||
// several common interfaces (in addition to those provided through nsIURI).
|
||||
// So I decided to group them all in this implementation so we don't have to
|
||||
// duplicate the code.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NS_MSG_BASE nsMsgMailNewsUrl : public nsIMsgMailNewsUrl
|
||||
{
|
||||
public:
|
||||
nsMsgMailNewsUrl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGMAILNEWSURL
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSIURL
|
||||
|
||||
protected:
|
||||
virtual ~nsMsgMailNewsUrl();
|
||||
|
||||
// a helper function I needed from derived urls...
|
||||
virtual const char * GetUserName() = 0;
|
||||
|
||||
nsCOMPtr<nsIURL> m_baseURL;
|
||||
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
|
||||
char *m_errorMessage;
|
||||
PRBool m_runningUrl;
|
||||
PRBool m_updatingFolder;
|
||||
|
||||
// manager of all of current url listeners....
|
||||
nsCOMPtr<nsIUrlListenerManager> m_urlListeners;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsMsgMailNewsUrl_h___ */
|
||||
369
mozilla/mailnews/base/util/nsMsgProtocol.cpp
Normal file
369
mozilla/mailnews/base/util/nsMsgProtocol.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgProtocol.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIIOService.h"
|
||||
|
||||
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsMsgProtocol, nsIStreamListener, nsIStreamObserver, nsIChannel)
|
||||
|
||||
nsMsgProtocol::nsMsgProtocol()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_flags = 0;
|
||||
m_startPosition = 0;
|
||||
m_readCount = 0;
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
|
||||
m_tempMsgFileSpec = nsSpecialSystemDirectory(nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
||||
m_tempMsgFileSpec += "tempMessage.eml";
|
||||
}
|
||||
|
||||
nsMsgProtocol::~nsMsgProtocol()
|
||||
{}
|
||||
|
||||
nsresult nsMsgProtocol::OpenNetworkSocket(nsIURI * aURL) // open a connection on this url
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsXPIDLCString hostName;
|
||||
PRInt32 port = 0;
|
||||
|
||||
m_readCount = -1; // with socket connections we want to read as much data as arrives
|
||||
m_startPosition = 0;
|
||||
|
||||
NS_WITH_SERVICE(nsISocketTransportService, socketService, kSocketTransportServiceCID, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aURL)
|
||||
{
|
||||
aURL->GetPort(&port);
|
||||
aURL->GetHost(getter_Copies(hostName));
|
||||
|
||||
rv = socketService->CreateTransport(hostName, port, nsnull, getter_AddRefs(m_channel));
|
||||
if (NS_SUCCEEDED(rv) && m_channel)
|
||||
{
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
rv = SetupTransportState();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::OpenFileSocket(nsIURI * aURL, const nsFileSpec * aFileSpec, PRUint32 aStartPosition, PRInt32 aReadCount)
|
||||
{
|
||||
// mscott - file needs to be encoded directly into aURL. I should be able to get
|
||||
// rid of this method completely.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
m_startPosition = aStartPosition;
|
||||
m_readCount = aReadCount;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aURL)
|
||||
{
|
||||
// extract the file path from the uri...
|
||||
nsXPIDLCString filePath;
|
||||
aURL->GetPath(getter_Copies(filePath));
|
||||
char * urlSpec = PR_smprintf("file://%s", (const char *) filePath);
|
||||
|
||||
rv = netService->NewChannel("Load", urlSpec,
|
||||
nsnull, // null base URI
|
||||
nsnull, // null load group
|
||||
nsnull, // null eventsink getter
|
||||
getter_AddRefs(m_channel));
|
||||
PR_FREEIF(urlSpec);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && m_channel)
|
||||
{
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
// rv = SetupTransportState();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::SetupTransportState()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!m_socketIsOpen && m_channel)
|
||||
{
|
||||
rv = m_channel->OpenOutputStream(0 /* start position */, getter_AddRefs(m_outputStream));
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create an output stream");
|
||||
// we want to open the stream
|
||||
} // if m_transport
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::CloseSocket()
|
||||
{
|
||||
// release all of our socket state
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
m_outputStream = null_nsCOMPtr();
|
||||
m_channel = null_nsCOMPtr();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the data contained in dataBuffer into the current output stream. It also informs
|
||||
* the transport layer that this data is now available for transmission.
|
||||
* Returns a positive number for success, 0 for failure (not all the bytes were written to the
|
||||
* stream, etc). We need to make another pass through this file to install an error system (mscott)
|
||||
*/
|
||||
|
||||
PRInt32 nsMsgProtocol::SendData(nsIURI * aURL, const char * dataBuffer)
|
||||
{
|
||||
PRUint32 writeCount = 0;
|
||||
PRInt32 status = 0;
|
||||
|
||||
// NS_PRECONDITION(m_outputStream, "oops....we don't have an output stream...how did that happen?");
|
||||
if (dataBuffer && m_outputStream)
|
||||
{
|
||||
status = m_outputStream->Write(dataBuffer, PL_strlen(dataBuffer), &writeCount);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Whenever data arrives from the connection, core netlib notifices the protocol by calling
|
||||
// OnDataAvailable. We then read and process the incoming data from the input stream.
|
||||
NS_IMETHODIMP nsMsgProtocol::OnDataAvailable(nsIChannel * /* aChannel */, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
|
||||
{
|
||||
// right now, this really just means turn around and churn through the state machine
|
||||
nsCOMPtr<nsIURI> uri = do_QueryInterface(ctxt);
|
||||
return ProcessProtocolState(uri, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OnStartRequest(nsIChannel * aChannel, nsISupports *ctxt)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
||||
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK);
|
||||
|
||||
// if we are set up as a channel, we should notify our channel listener that we are starting...
|
||||
// so pass in ourself as the channel and not the underlying socket or file channel the protocol
|
||||
// happens to be using
|
||||
if (m_channelListener)
|
||||
rv = m_channelListener->OnStartRequest(this, m_channelContext);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// stop binding is a "notification" informing us that the stream associated with aURL is going away.
|
||||
NS_IMETHODIMP nsMsgProtocol::OnStopRequest(nsIChannel * aChannel, nsISupports *ctxt, nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
||||
rv = aMsgUrl->SetUrlState(PR_FALSE, aStatus);
|
||||
|
||||
// if we are set up as a channel, we should notify our channel listener that we are starting...
|
||||
// so pass in ourself as the channel and not the underlying socket or file channel the protocol
|
||||
// happens to be using
|
||||
if (m_channelListener)
|
||||
rv = m_channelListener->OnStopRequest(this, m_channelContext, aStatus, aMsg);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||
{
|
||||
// okay now kick us off to the next state...
|
||||
// our first state is a process state so drive the state machine...
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(aURL);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK); // set the url as a url currently being run...
|
||||
|
||||
// if the url is given a stream consumer then we should use it to forward calls to...
|
||||
if (!m_channelListener && aConsumer) // if we don't have a registered listener already
|
||||
{
|
||||
m_channelListener = do_QueryInterface(aConsumer);
|
||||
if (!m_channelContext)
|
||||
m_channelContext = do_QueryInterface(aURL);
|
||||
}
|
||||
|
||||
if (!m_socketIsOpen)
|
||||
{
|
||||
nsCOMPtr<nsISupports> urlSupports = do_QueryInterface(aURL);
|
||||
|
||||
// put us in a state where we are always notified of incoming data
|
||||
m_channel->AsyncRead(m_startPosition, m_readCount, urlSupports ,this /* stream observer */);
|
||||
m_socketIsOpen = PR_TRUE; // mark the channel as open
|
||||
} // if we got an event queue service
|
||||
else // the connection is already open so we should begin processing our new url...
|
||||
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The rest of this file is mostly nsIChannel mumbo jumbo stuff
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult nsMsgProtocol::SetUrl(nsIURI * aURL)
|
||||
{
|
||||
m_url = dont_QueryInterface(aURL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::SetLoadGroup(nsILoadGroup * aLoadGroup)
|
||||
{
|
||||
m_loadGroup = dont_QueryInterface(aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aURI)
|
||||
{
|
||||
if (m_url)
|
||||
rv = m_url->QueryInterface(NS_GET_IID(nsIURI), (void **) aURI);
|
||||
else
|
||||
*aURI = nsnull;
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
|
||||
{
|
||||
// set the stream listener and then load the url
|
||||
m_channelContext = ctxt;
|
||||
m_channelListener = listener;
|
||||
|
||||
// the following load group code is completely bogus....
|
||||
nsresult rv = NS_OK;
|
||||
if (m_loadGroup)
|
||||
{
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = m_loadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> newListener;
|
||||
rv = factory->CreateLoadGroupListener(m_channelListener, getter_AddRefs(newListener));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_channelListener = newListener;
|
||||
}
|
||||
} // if aLoadGroup
|
||||
|
||||
return LoadUrl(m_url, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition, PRInt32 writeCount, nsISupports *ctxt, nsIStreamObserver *observer)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetContentType(char * *aContentType)
|
||||
{
|
||||
*aContentType = nsCRT::strdup("message/rfc822");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetContentLength(PRInt32 * aContentLength)
|
||||
{
|
||||
*aContentLength = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetOwner(nsISupports * *aPrincipal)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::SetOwner(nsISupports * aPrincipal)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetLoadGroup(nsILoadGroup * *aLoadGroup)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// From nsIRequest
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::IsPending(PRBool *result)
|
||||
{
|
||||
*result = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Cancel()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Suspend()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Resume()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
108
mozilla/mailnews/base/util/nsMsgProtocol.h
Normal file
108
mozilla/mailnews/base/util/nsMsgProtocol.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgProtocol_h__
|
||||
#define nsMsgProtocol_h__
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// This is a helper class used to encapsulate code shared between all of the
|
||||
// mailnews protocol objects (imap, news, pop, smtp, etc.) In particular,
|
||||
// it unifies the core networking code for the protocols. My hope is that
|
||||
// this will make unification with Necko easier as we'll only have to change
|
||||
// this class and not all of the mailnews protocols.
|
||||
class NS_MSG_BASE nsMsgProtocol : public nsIStreamListener, public nsIChannel
|
||||
{
|
||||
public:
|
||||
nsMsgProtocol();
|
||||
virtual ~nsMsgProtocol();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
// nsIChannel support
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// LoadUrl -- A protocol typically overrides this function, sets up any local state for the url and
|
||||
// then calls the base class which opens the socket if it needs opened. If the socket is
|
||||
// already opened then we just call ProcessProtocolState to start the churning process.
|
||||
// aConsumer is the consumer for the url. It can be null if this argument is not appropriate
|
||||
virtual nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer = nsnull);
|
||||
|
||||
virtual nsresult SetUrl(nsIURI * aURL); // sometimes we want to set the url before we load it
|
||||
virtual nsresult SetLoadGroup(nsILoadGroup * aLoadGroup);
|
||||
|
||||
// Flag manipulators
|
||||
PRBool TestFlag (PRUint32 flag) {return flag & m_flags;}
|
||||
void SetFlag (PRUint32 flag) { m_flags |= flag; }
|
||||
void ClearFlag (PRUint32 flag) { m_flags &= ~flag; }
|
||||
|
||||
protected:
|
||||
// methods for opening and closing a socket with core netlib....
|
||||
// mscott -okay this is lame. I should break this up into a file protocol and a socket based
|
||||
// protocool class instead of cheating and putting both methods here...
|
||||
virtual nsresult OpenNetworkSocket(nsIURI * aURL); // open a connection on this url
|
||||
virtual nsresult OpenFileSocket(nsIURI * aURL, const nsFileSpec * aFileSpec, PRUint32 aStartPosition, PRInt32 aReadCount); // used to open a file socket connection
|
||||
|
||||
// a Protocol typically overrides this method. They free any of their own connection state and then
|
||||
// they call up into the base class to free the generic connection objects
|
||||
virtual nsresult CloseSocket();
|
||||
|
||||
virtual nsresult SetupTransportState(); // private method used by OpenNetworkSocket and OpenFileSocket
|
||||
|
||||
// ProcessProtocolState - This is the function that gets churned by calls to OnDataAvailable.
|
||||
// As data arrives on the socket, OnDataAvailable calls ProcessProtocolState.
|
||||
|
||||
virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream,
|
||||
PRUint32 sourceOffset, PRUint32 length) = 0;
|
||||
|
||||
// SendData -- Writes the data contained in dataBuffer into the current output stream.
|
||||
// It also informs the transport layer that this data is now available for transmission.
|
||||
// Returns a positive number for success, 0 for failure (not all the bytes were written to the
|
||||
// stream, etc).
|
||||
virtual PRInt32 SendData(nsIURI * aURL, const char * dataBuffer);
|
||||
|
||||
// Ouput stream for writing commands to the socket
|
||||
nsCOMPtr<nsIChannel> m_channel;
|
||||
nsCOMPtr<nsIOutputStream> m_outputStream; // this will be obtained from the transport interface
|
||||
|
||||
PRBool m_socketIsOpen; // mscott: we should look into keeping this state in the nsSocketTransport...
|
||||
// I'm using it to make sure I open the socket the first time a URL is loaded into the connection
|
||||
PRUint32 m_flags; // used to store flag information
|
||||
PRUint32 m_startPosition;
|
||||
PRInt32 m_readCount;
|
||||
|
||||
nsFileSpec m_tempMsgFileSpec; // we currently have a hack where displaying a msg involves writing it to a temp file first
|
||||
|
||||
// the following is a catch all for nsIChannel related data
|
||||
nsCOMPtr<nsIURI> m_url; // the running url
|
||||
nsCOMPtr<nsIStreamListener> m_channelListener;
|
||||
nsCOMPtr<nsISupports> m_channelContext;
|
||||
nsCOMPtr<nsILoadGroup> m_loadGroup;
|
||||
};
|
||||
|
||||
#endif /* nsMsgProtocol_h__ */
|
||||
99
mozilla/mailnews/base/util/nsMsgTxn.cpp
Normal file
99
mozilla/mailnews/base/util/nsMsgTxn.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998, 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsMsgTxn.h"
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kITransactionIID, NS_ITRANSACTION_IID);
|
||||
|
||||
NS_IMPL_ADDREF(nsMsgTxn)
|
||||
NS_IMPL_RELEASE(nsMsgTxn)
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
nsMsgTxn::nsMsgTxn()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMsgTxn::~nsMsgTxn()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Do(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetIsTransient(PRBool *aIsTransient)
|
||||
{
|
||||
if (nsnull!=aIsTransient)
|
||||
*aIsTransient = PR_FALSE;
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Write(nsIOutputStream *aOutputStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetUndoString(nsString *aString)
|
||||
{
|
||||
if (nsnull!=aString)
|
||||
*aString="Undo";
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetRedoString(nsString *aString)
|
||||
{
|
||||
if (nsnull!=aString)
|
||||
*aString="Redo";
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kITransactionIID)) {
|
||||
*aInstancePtr = (void*)(nsITransaction*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
*aInstancePtr = 0;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
57
mozilla/mailnews/base/util/nsMsgTxn.h
Normal file
57
mozilla/mailnews/base/util/nsMsgTxn.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998, 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgTxn_h__
|
||||
#define nsMsgTxn_h__
|
||||
|
||||
#include "nsITransaction.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
#define NS_MESSAGETRANSACTION_IID \
|
||||
{ /* da621b30-1efc-11d3-abe4-00805f8ac968 */ \
|
||||
0xda621b30, 0x1efc, 0x11d3, \
|
||||
{ 0xab, 0xe4, 0x00, 0x80, 0x5f, 0x8a, 0xc9, 0x68 } }
|
||||
/**
|
||||
* base class for all message undo/redo transactions.
|
||||
*/
|
||||
class NS_MSG_BASE nsMsgTxn : public nsITransaction
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMsgTxn();
|
||||
virtual ~nsMsgTxn();
|
||||
|
||||
NS_IMETHOD Do(void);
|
||||
|
||||
NS_IMETHOD Undo(void) = 0;
|
||||
|
||||
NS_IMETHOD Redo(void) = 0;
|
||||
|
||||
NS_IMETHOD GetIsTransient(PRBool *aIsTransient);
|
||||
|
||||
NS_IMETHOD Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||
|
||||
NS_IMETHOD Write(nsIOutputStream *aOutputStream);
|
||||
|
||||
NS_IMETHOD GetUndoString(nsString *aString);
|
||||
|
||||
NS_IMETHOD GetRedoString(nsString *aString);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
326
mozilla/mailnews/base/util/nsMsgUtils.cpp
Normal file
326
mozilla/mailnews/base/util/nsMsgUtils.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIImapUrl.h"
|
||||
#include "nsIMailboxUrl.h"
|
||||
#include "nsINntpUrl.h"
|
||||
#include "nsMsgNewsCID.h"
|
||||
#include "nsMsgLocalCID.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgImapCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
|
||||
static NS_DEFINE_CID(kCMailboxUrl, NS_MAILBOXURL_CID);
|
||||
static NS_DEFINE_CID(kCNntpUrlCID, NS_NNTPURL_CID);
|
||||
|
||||
#if defined(DEBUG_sspitzer_) || defined(DEBUG_seth_)
|
||||
#define DEBUG_NS_MsgHashIfNecessary 1
|
||||
#endif
|
||||
|
||||
nsresult GetMessageServiceProgIDForURI(const char *uri, nsString &progID)
|
||||
{
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
//Find protocol
|
||||
nsString uriStr = uri;
|
||||
PRInt32 pos = uriStr.FindChar(':');
|
||||
if(pos == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsString protocol;
|
||||
uriStr.Left(protocol, pos);
|
||||
|
||||
//Build message service progid
|
||||
progID = "component://netscape/messenger/messageservice;type=";
|
||||
progID += protocol;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult GetMessageServiceFromURI(const char *uri, nsIMsgMessageService **messageService)
|
||||
{
|
||||
|
||||
nsAutoString progID;
|
||||
nsresult rv;
|
||||
|
||||
rv = GetMessageServiceProgIDForURI(uri, progID);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = nsServiceManager::GetService((const char *) nsCAutoString(progID), nsCOMTypeInfo<nsIMsgMessageService>::GetIID(),
|
||||
(nsISupports**)messageService, nsnull);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult ReleaseMessageServiceFromURI(const char *uri, nsIMsgMessageService *messageService)
|
||||
{
|
||||
nsAutoString progID;
|
||||
nsresult rv;
|
||||
|
||||
rv = GetMessageServiceProgIDForURI(uri, progID);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = nsServiceManager::ReleaseService(nsCAutoString(progID), messageService);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult CreateStartupUrl(char *uri, nsIURI** aUrl)
|
||||
{
|
||||
nsresult rv = NS_ERROR_NULL_POINTER;
|
||||
if (!uri || !*uri || !aUrl) return rv;
|
||||
*aUrl = nsnull;
|
||||
if (PL_strncasecmp(uri, "imap", 4) == 0)
|
||||
{
|
||||
nsCOMPtr<nsIImapUrl> imapUrl;
|
||||
rv = nsComponentManager::CreateInstance(kImapUrlCID, nsnull,
|
||||
nsIImapUrl::GetIID(),
|
||||
getter_AddRefs(imapUrl));
|
||||
if (NS_SUCCEEDED(rv) && imapUrl)
|
||||
rv = imapUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
else if (PL_strncasecmp(uri, "mailbox", 7) == 0)
|
||||
{
|
||||
nsCOMPtr<nsIMailboxUrl> mailboxUrl;
|
||||
rv = nsComponentManager::CreateInstance(kCMailboxUrl, nsnull,
|
||||
nsIMailboxUrl::GetIID(),
|
||||
getter_AddRefs(mailboxUrl));
|
||||
if (NS_SUCCEEDED(rv) && mailboxUrl)
|
||||
rv = mailboxUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
else if (PL_strncasecmp(uri, "news", 4) == 0)
|
||||
{
|
||||
nsCOMPtr<nsINntpUrl> nntpUrl;
|
||||
rv = nsComponentManager::CreateInstance(kCNntpUrlCID, nsnull,
|
||||
nsINntpUrl::GetIID(),
|
||||
getter_AddRefs(nntpUrl));
|
||||
if (NS_SUCCEEDED(rv) && nntpUrl)
|
||||
rv = nntpUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
if (*aUrl)
|
||||
(*aUrl)->SetSpec(uri);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMessageFromMsgHdrEnumerator, nsCOMTypeInfo<nsISimpleEnumerator>::GetIID())
|
||||
|
||||
nsMessageFromMsgHdrEnumerator::nsMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mSrcEnumerator = dont_QueryInterface(srcEnumerator);
|
||||
mFolder = dont_QueryInterface(folder);
|
||||
|
||||
}
|
||||
|
||||
nsMessageFromMsgHdrEnumerator::~nsMessageFromMsgHdrEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageFromMsgHdrEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
nsresult rv;
|
||||
|
||||
rv = mSrcEnumerator->GetNext(getter_AddRefs(currentItem));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
msgDBHdr = do_QueryInterface(currentItem, &rv);
|
||||
}
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = mFolder->CreateMessageFromMsgDBHdr(msgDBHdr, getter_AddRefs(message));
|
||||
}
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
currentItem = do_QueryInterface(message, &rv);
|
||||
*aItem = currentItem;
|
||||
NS_IF_ADDREF(*aItem);
|
||||
}
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"getnext shouldn't fail");
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageFromMsgHdrEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
return mSrcEnumerator->HasMoreElements(aResult);
|
||||
}
|
||||
|
||||
nsresult NS_NewMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder,
|
||||
nsMessageFromMsgHdrEnumerator **messageEnumerator)
|
||||
{
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*messageEnumerator = new nsMessageFromMsgHdrEnumerator(srcEnumerator, folder);
|
||||
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*messageEnumerator);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
// Where should this live? It's a utility used to convert a string priority, e.g., "High, Low, Normal" to an enum.
|
||||
// Perhaps we should have an interface that groups together all these utilities...
|
||||
nsresult NS_MsgGetPriorityFromString(const char *priority, nsMsgPriority *outPriority)
|
||||
{
|
||||
if (!outPriority)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsMsgPriority retPriority = nsMsgPriorityNormal;
|
||||
|
||||
if (PL_strcasestr(priority, "Normal") != NULL)
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
else if (PL_strcasestr(priority, "Lowest") != NULL)
|
||||
retPriority = nsMsgPriorityLowest;
|
||||
else if (PL_strcasestr(priority, "Highest") != NULL)
|
||||
retPriority = nsMsgPriorityHighest;
|
||||
else if (PL_strcasestr(priority, "High") != NULL ||
|
||||
PL_strcasestr(priority, "Urgent") != NULL)
|
||||
retPriority = nsMsgPriorityHigh;
|
||||
else if (PL_strcasestr(priority, "Low") != NULL ||
|
||||
PL_strcasestr(priority, "Non-urgent") != NULL)
|
||||
retPriority = nsMsgPriorityLow;
|
||||
else if (PL_strcasestr(priority, "1") != NULL)
|
||||
retPriority = nsMsgPriorityHighest;
|
||||
else if (PL_strcasestr(priority, "2") != NULL)
|
||||
retPriority = nsMsgPriorityHigh;
|
||||
else if (PL_strcasestr(priority, "3") != NULL)
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
else if (PL_strcasestr(priority, "4") != NULL)
|
||||
retPriority = nsMsgPriorityLow;
|
||||
else if (PL_strcasestr(priority, "5") != NULL)
|
||||
retPriority = nsMsgPriorityLowest;
|
||||
else
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
*outPriority = retPriority;
|
||||
return NS_OK;
|
||||
//return nsMsgNoPriority;
|
||||
}
|
||||
|
||||
|
||||
nsresult NS_MsgGetUntranslatedPriorityName (nsMsgPriority p, nsString *outName)
|
||||
{
|
||||
if (!outName)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
switch (p)
|
||||
{
|
||||
case nsMsgPriorityNotSet:
|
||||
case nsMsgPriorityNone:
|
||||
*outName = "None";
|
||||
break;
|
||||
case nsMsgPriorityLowest:
|
||||
*outName = "Lowest";
|
||||
break;
|
||||
case nsMsgPriorityLow:
|
||||
*outName = "Low";
|
||||
break;
|
||||
case nsMsgPriorityNormal:
|
||||
*outName = "Normal";
|
||||
break;
|
||||
case nsMsgPriorityHigh:
|
||||
*outName = "High";
|
||||
break;
|
||||
case nsMsgPriorityHighest:
|
||||
*outName = "Highest";
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(PR_FALSE, "invalid priority value");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* this used to be XP_StringHash2 from xp_hash.c */
|
||||
/* phong's linear congruential hash */
|
||||
static PRUint32 StringHash(const char *ubuf)
|
||||
{
|
||||
unsigned char * buf = (unsigned char*) ubuf;
|
||||
PRUint32 h=1;
|
||||
while(*buf) {
|
||||
h = 0x63c63cd9*h + 0x9c39c33d + (int32)*buf;
|
||||
buf++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
|
||||
{
|
||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||
const PRUint32 MAX_LEN = 8;
|
||||
#elif defined(XP_MAC)
|
||||
const PRUint32 MAX_LEN = 25;
|
||||
#elif defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
|
||||
const PRUint32 MAX_LEN = 55;
|
||||
#else
|
||||
#error need_to_define_your_max_filename_length
|
||||
#endif
|
||||
nsCAutoString str(name);
|
||||
|
||||
#ifdef DEBUG_NS_MsgHashIfNecessary
|
||||
printf("in: %s\n",str.GetBuffer());
|
||||
#endif
|
||||
|
||||
// Given a name, use either that name, if it fits on our
|
||||
// filesystem, or a hashified version of it, if the name is too
|
||||
// long to fit.
|
||||
char hashedname[MAX_LEN + 1];
|
||||
PRBool needshash = PL_strlen(str.GetBuffer()) > MAX_LEN;
|
||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||
if (!needshash) {
|
||||
needshash = PL_strchr(str.GetBuffer(), '.') != NULL ||
|
||||
PL_strchr(str.GetBuffer(), ':') != NULL;
|
||||
}
|
||||
#endif
|
||||
PL_strncpy(hashedname, str.GetBuffer(), MAX_LEN + 1);
|
||||
if (needshash) {
|
||||
PR_snprintf(hashedname + MAX_LEN - 8, 9, "%08lx",
|
||||
(unsigned long) StringHash(str.GetBuffer()));
|
||||
}
|
||||
name = hashedname;
|
||||
#ifdef DEBUG_NS_MsgHashIfNecessary
|
||||
printf("out: %s\n",hashedname);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
67
mozilla/mailnews/base/util/nsMsgUtils.h
Normal file
67
mozilla/mailnews/base/util/nsMsgUtils.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NSMSGUTILS_H
|
||||
#define _NSMSGUTILS_H
|
||||
|
||||
#include "nsIURL.h"
|
||||
#include "nsIMsgMessageService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "msgCore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
//These are utility functions that can used throughout the mailnews code
|
||||
|
||||
//Utilities for getting a message service.
|
||||
NS_MSG_BASE nsresult GetMessageServiceProgIDForURI(const char *uri, nsString &progID);
|
||||
//Use ReleaseMessageServiceFromURI to release the service.
|
||||
NS_MSG_BASE nsresult GetMessageServiceFromURI(const char *uri, nsIMsgMessageService **messageService);
|
||||
NS_MSG_BASE nsresult ReleaseMessageServiceFromURI(const char *uri, nsIMsgMessageService *messageService);
|
||||
|
||||
NS_MSG_BASE nsresult CreateStartupUrl(char *uri, nsIURI** aUrl);
|
||||
|
||||
//An enumerator for converting nsIMsgHdrs to nsIMessages.
|
||||
class NS_MSG_BASE nsMessageFromMsgHdrEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
protected:
|
||||
nsCOMPtr<nsISimpleEnumerator> mSrcEnumerator;
|
||||
nsCOMPtr<nsIMsgFolder> mFolder;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
nsMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator, nsIMsgFolder *folder);
|
||||
nsMessageFromMsgHdrEnumerator(){} //Default constructor that does nothing so nsComPtr will work.
|
||||
virtual ~nsMessageFromMsgHdrEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
};
|
||||
|
||||
NS_MSG_BASE nsresult NS_NewMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder,
|
||||
nsMessageFromMsgHdrEnumerator **messageEnumerator);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgGetPriorityFromString(const char *priority, nsMsgPriority *outPriority);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgGetUntranslatedPriorityName (nsMsgPriority p, nsString *outName);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgHashIfNecessary(nsCAutoString &name);
|
||||
|
||||
#endif
|
||||
|
||||
71
mozilla/mailnews/base/util/nsNewsSummarySpec.cpp
Normal file
71
mozilla/mailnews/base/util/nsNewsSummarySpec.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsNewsSummarySpec.h"
|
||||
#include "plstr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsNewsSummarySpec);
|
||||
|
||||
nsNewsSummarySpec::~nsNewsSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsNewsSummarySpec);
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const char *folderPath)
|
||||
: nsFileSpec(folderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const nsFileSpec& inFolderPath)
|
||||
: nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const nsFilePath &inFolderPath) : nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
void nsNewsSummarySpec::SetFolderName(const char *folderPath)
|
||||
{
|
||||
*this = folderPath;
|
||||
}
|
||||
|
||||
void nsNewsSummarySpec::CreateSummaryFileName()
|
||||
{
|
||||
char *leafName = GetLeafName();
|
||||
|
||||
nsCAutoString fullLeafName((const char*)leafName);
|
||||
|
||||
// Append .msf (message summary file)
|
||||
fullLeafName += ".msf";
|
||||
|
||||
SetLeafName(fullLeafName.GetBuffer());
|
||||
PL_strfree(leafName);
|
||||
}
|
||||
45
mozilla/mailnews/base/util/nsNewsSummarySpec.h
Normal file
45
mozilla/mailnews/base/util/nsNewsSummarySpec.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsNewsSummarySpec_H
|
||||
#define _nsNewsSummarySpec_H
|
||||
|
||||
#include "nsFileSpec.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
// Class to name a summary file for a newsgroup,
|
||||
// given a full folder file spec.
|
||||
// Note this class expects the invoking code to fully specify the folder path.
|
||||
// This class does NOT prepend the local folder directory, or put .sbd on the containing
|
||||
// directory names.
|
||||
class NS_MSG_BASE nsNewsSummarySpec : public nsFileSpec
|
||||
{
|
||||
public:
|
||||
nsNewsSummarySpec();
|
||||
nsNewsSummarySpec(const char *folderPath);
|
||||
nsNewsSummarySpec(const nsFileSpec& inFolderPath);
|
||||
nsNewsSummarySpec(const nsFilePath &inFolderPath);
|
||||
~nsNewsSummarySpec();
|
||||
void SetFolderName(const char *folderPath);
|
||||
|
||||
protected:
|
||||
void CreateSummaryFileName();
|
||||
|
||||
};
|
||||
|
||||
#endif /* _nsNewsSummarySpec_H */
|
||||
277
mozilla/mailnews/base/util/nsUInt32Array.cpp
Normal file
277
mozilla/mailnews/base/util/nsUInt32Array.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "prlog.h"
|
||||
|
||||
#include "MailNewsTypes.h"
|
||||
#include "nsUInt32Array.h"
|
||||
#include "nsQuickSort.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsUInt32Array);
|
||||
|
||||
nsUInt32Array::nsUInt32Array()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsUInt32Array);
|
||||
m_nSize = 0;
|
||||
m_nMaxSize = 0;
|
||||
m_nGrowBy = 0;
|
||||
m_pData = NULL;
|
||||
}
|
||||
|
||||
nsUInt32Array::~nsUInt32Array()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsUInt32Array);
|
||||
SetSize(0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 nsUInt32Array::GetSize() const
|
||||
{
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
PRBool nsUInt32Array::SetSize(PRUint32 nSize,
|
||||
PRBool adjustGrowth,
|
||||
PRUint32 nGrowBy)
|
||||
{
|
||||
if (adjustGrowth)
|
||||
m_nGrowBy = nGrowBy;
|
||||
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
if (nSize > MAX_ARR_ELEMS);
|
||||
{
|
||||
PR_ASSERT(nSize <= MAX_ARR_ELEMS); // Will fail
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nSize == 0)
|
||||
{
|
||||
// Remove all elements
|
||||
PR_Free(m_pData);
|
||||
m_nSize = 0;
|
||||
m_nMaxSize = 0;
|
||||
m_pData = NULL;
|
||||
}
|
||||
else if (m_pData == NULL)
|
||||
{
|
||||
// Create a new array
|
||||
m_nMaxSize = PR_MAX(8, nSize);
|
||||
m_pData = (PRUint32 *)PR_Calloc(1, m_nMaxSize * sizeof(PRUint32));
|
||||
if (m_pData)
|
||||
m_nSize = nSize;
|
||||
else
|
||||
m_nSize = m_nMaxSize = 0;
|
||||
}
|
||||
else if (nSize <= m_nMaxSize)
|
||||
{
|
||||
// The new size is within the current maximum size, make sure new
|
||||
// elements are to initialized to zero
|
||||
if (nSize > m_nSize)
|
||||
nsCRT::memset(&m_pData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
|
||||
m_nSize = nSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The array needs to grow, figure out how much
|
||||
PRUint32 nMaxSize;
|
||||
nGrowBy = PR_MAX(m_nGrowBy, PR_MIN(1024, PR_MAX(8, m_nSize / 8)));
|
||||
nMaxSize = PR_MAX(nSize, m_nMaxSize + nGrowBy);
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
nMaxSize = PR_MIN(MAX_ARR_ELEMS, nMaxSize);
|
||||
#endif
|
||||
|
||||
PRUint32 *pNewData = (PRUint32 *)PR_Malloc(nMaxSize * sizeof(PRUint32));
|
||||
if (pNewData)
|
||||
{
|
||||
// Copy the data from the old array to the new one
|
||||
nsCRT::memcpy(pNewData, m_pData, m_nSize * sizeof(PRUint32));
|
||||
|
||||
// Zero out the remaining elements
|
||||
nsCRT::memset(&pNewData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
m_nSize = nSize;
|
||||
m_nMaxSize = nMaxSize;
|
||||
|
||||
// Free the old array
|
||||
PR_Free(m_pData);
|
||||
m_pData = pNewData;
|
||||
}
|
||||
}
|
||||
|
||||
return nSize == m_nSize;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 &nsUInt32Array::ElementAt(PRUint32 nIndex)
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
return m_pData[nIndex];
|
||||
}
|
||||
|
||||
PRUint32 nsUInt32Array::GetAt(PRUint32 nIndex) const
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
return m_pData[nIndex];
|
||||
}
|
||||
|
||||
PRUint32 *nsUInt32Array::GetData()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
void nsUInt32Array::SetAt(PRUint32 nIndex, PRUint32 newElement)
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
m_pData[nIndex] = newElement;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 nsUInt32Array::Add(PRUint32 newElement)
|
||||
{
|
||||
PRUint32 nIndex = m_nSize;
|
||||
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
if (nIndex >= MAX_ARR_ELEMS)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
SetAtGrow(nIndex, newElement);
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
PRUint32 nsUInt32Array::Add(PRUint32 *elementPtr, PRUint32 numElements)
|
||||
{
|
||||
if (SetSize(m_nSize + numElements))
|
||||
nsCRT::memcpy(m_pData + m_nSize, elementPtr, numElements * sizeof(PRUint32));
|
||||
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
PRUint32 *nsUInt32Array::CloneData()
|
||||
{
|
||||
PRUint32 *copyOfData = (PRUint32 *)PR_Malloc(m_nSize * sizeof(PRUint32));
|
||||
if (copyOfData)
|
||||
nsCRT::memcpy(copyOfData, m_pData, m_nSize * sizeof(PRUint32));
|
||||
|
||||
return copyOfData;
|
||||
}
|
||||
|
||||
void nsUInt32Array::InsertAt(PRUint32 nIndex, PRUint32 newElement, PRUint32 nCount)
|
||||
{
|
||||
PR_ASSERT(nCount > 0);
|
||||
|
||||
if (nIndex >= m_nSize)
|
||||
{
|
||||
// If the new element is after the end of the array, grow the array
|
||||
SetSize(nIndex + nCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The element is being insert inside the array
|
||||
int nOldSize = m_nSize;
|
||||
SetSize(m_nSize + nCount);
|
||||
|
||||
// Move the data after the insertion point
|
||||
nsCRT::memmove(&m_pData[nIndex + nCount], &m_pData[nIndex],
|
||||
(nOldSize - nIndex) * sizeof(PRUint32));
|
||||
}
|
||||
|
||||
// Insert the new elements
|
||||
PR_ASSERT(nIndex + nCount <= m_nSize);
|
||||
while (nCount--)
|
||||
m_pData[nIndex++] = newElement;
|
||||
}
|
||||
|
||||
void nsUInt32Array::InsertAt(PRUint32 nStartIndex, const nsUInt32Array *pNewArray)
|
||||
{
|
||||
PR_ASSERT(pNewArray != NULL);
|
||||
|
||||
if (pNewArray->GetSize() > 0)
|
||||
{
|
||||
InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
|
||||
for (PRUint32 i = 1; i < pNewArray->GetSize(); i++)
|
||||
m_pData[nStartIndex + i] = pNewArray->GetAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
void nsUInt32Array::RemoveAll()
|
||||
{
|
||||
SetSize(0);
|
||||
}
|
||||
|
||||
void nsUInt32Array::RemoveAt(PRUint32 nIndex, PRUint32 nCount)
|
||||
{
|
||||
PR_ASSERT(nIndex + nCount <= m_nSize);
|
||||
|
||||
if (nCount > 0)
|
||||
{
|
||||
// Make sure not to overstep the end of the array
|
||||
int nMoveCount = m_nSize - (nIndex + nCount);
|
||||
if (nCount && nMoveCount)
|
||||
nsCRT::memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
|
||||
nMoveCount * sizeof(PRUint32));
|
||||
|
||||
m_nSize -= nCount;
|
||||
}
|
||||
}
|
||||
|
||||
void nsUInt32Array::SetAtGrow(PRUint32 nIndex, PRUint32 newElement)
|
||||
{
|
||||
if (nIndex >= m_nSize)
|
||||
SetSize(nIndex+1);
|
||||
m_pData[nIndex] = newElement;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void nsUInt32Array::CopyArray(nsUInt32Array *oldA)
|
||||
{
|
||||
CopyArray(*oldA);
|
||||
}
|
||||
|
||||
void nsUInt32Array::CopyArray(nsUInt32Array &oldA)
|
||||
{
|
||||
if (m_pData)
|
||||
PR_Free(m_pData);
|
||||
m_nSize = oldA.m_nSize;
|
||||
m_nMaxSize = oldA.m_nMaxSize;
|
||||
m_pData = (PRUint32 *)PR_Malloc(m_nSize * sizeof(PRUint32));
|
||||
if (m_pData)
|
||||
nsCRT::memcpy(m_pData, oldA.m_pData, m_nSize * sizeof(PRUint32));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int CompareDWord (const void *v1, const void *v2, void *)
|
||||
{
|
||||
// QuickSort callback to compare array values
|
||||
PRUint32 i1 = *(PRUint32 *)v1;
|
||||
PRUint32 i2 = *(PRUint32 *)v2;
|
||||
return i1 - i2;
|
||||
}
|
||||
|
||||
void nsUInt32Array::QuickSort (int (*compare) (const void *elem1, const void *elem2, void *data))
|
||||
{
|
||||
if (m_nSize > 1)
|
||||
NS_QuickSort(m_pData, m_nSize, sizeof(void*), compare ? compare : CompareDWord, nsnull);
|
||||
}
|
||||
73
mozilla/mailnews/base/util/nsUInt32Array.h
Normal file
73
mozilla/mailnews/base/util/nsUInt32Array.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef _nsUInt32Array_H_
|
||||
#define _nsUInt32Array_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prmem.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
class NS_MSG_BASE nsUInt32Array
|
||||
{
|
||||
public:
|
||||
// Construction/destruction
|
||||
nsUInt32Array();
|
||||
virtual ~nsUInt32Array();
|
||||
|
||||
// State/attribute member functions
|
||||
PRUint32 GetSize() const;
|
||||
PRBool SetSize(PRUint32 nNewSize, PRBool AdjustGrowth=PR_FALSE, PRUint32 nGrowBy = 0);
|
||||
|
||||
// Accessor member functions
|
||||
PRUint32 &ElementAt(PRUint32 nIndex);
|
||||
PRUint32 GetAt(PRUint32 nIndex) const;
|
||||
PRUint32 *GetData();
|
||||
void SetAt(PRUint32 nIndex, PRUint32 newElement);
|
||||
|
||||
// Insertion/deletion member functions
|
||||
PRUint32 Add(PRUint32 newElement);
|
||||
PRUint32 Add(PRUint32 *elementPtr, PRUint32 numElements);
|
||||
void InsertAt(PRUint32 nIndex, PRUint32 newElement, PRUint32 nCount = 1);
|
||||
void InsertAt(PRUint32 nStartIndex, const nsUInt32Array *pNewArray);
|
||||
void RemoveAll();
|
||||
void RemoveAt(PRUint32 nIndex, PRUint32 nCount = 1);
|
||||
void SetAtGrow(PRUint32 nIndex, PRUint32 newElement);
|
||||
|
||||
// Sorting member functions
|
||||
void QuickSort(int (*compare) (const void *elem1, const void *elem2, void *) = NULL);
|
||||
|
||||
// Overloaded operators
|
||||
PRUint32 operator[](PRUint32 nIndex) const { return GetAt(nIndex); }
|
||||
PRUint32 &operator[](PRUint32 nIndex) { return ElementAt(nIndex); }
|
||||
|
||||
// Miscellaneous member functions
|
||||
PRUint32 *CloneData();
|
||||
void CopyArray(nsUInt32Array *oldA);
|
||||
void CopyArray(nsUInt32Array &oldA);
|
||||
|
||||
protected:
|
||||
// Member data
|
||||
PRUint32 m_nSize;
|
||||
PRUint32 m_nMaxSize;
|
||||
PRUint32 m_nGrowBy;
|
||||
PRUint32* m_pData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _DWordArray_H_
|
||||
@@ -1,152 +0,0 @@
|
||||
#
|
||||
# ***** 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 Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems
|
||||
# Laboratories
|
||||
#
|
||||
# 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 *****
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
ifndef FREEBL_RECURSIVE_BUILD
|
||||
LIBRARY_NAME = freebl
|
||||
else
|
||||
ifdef USE_PURE_32
|
||||
CORE_DEPTH = ../../../..
|
||||
LIBRARY_NAME = freebl_pure32
|
||||
else
|
||||
LIBRARY_NAME = freebl_hybrid
|
||||
endif
|
||||
endif
|
||||
|
||||
# same version as rest of freebl
|
||||
LIBRARY_VERSION = _3
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
|
||||
|
||||
REQUIRES =
|
||||
|
||||
EXPORTS = \
|
||||
blapit.h \
|
||||
shsign.h \
|
||||
ecl-exp.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
blapi.h \
|
||||
secmpi.h \
|
||||
secrng.h \
|
||||
ec.h \
|
||||
ecl.h \
|
||||
ecl-curve.h \
|
||||
$(NULL)
|
||||
|
||||
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
|
||||
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c mpcpucache.c
|
||||
ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h
|
||||
ifdef NSS_ENABLE_ECC
|
||||
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
|
||||
ec2_aff.c ec2_mont.c ec2_proj.c \
|
||||
ec2_163.c ec2_193.c ec2_233.c \
|
||||
ecp_aff.c ecp_jac.c ecp_mont.c \
|
||||
ecp_192.c ecp_224.c \
|
||||
ec_naf.c ecp_jm.c
|
||||
else
|
||||
ECL_SRCS = $(NULL)
|
||||
endif
|
||||
|
||||
CSRCS = \
|
||||
ldvector.c \
|
||||
prng_fips1861.c \
|
||||
sysrand.c \
|
||||
sha_fast.c \
|
||||
md2.c \
|
||||
md5.c \
|
||||
sha512.c \
|
||||
alg2268.c \
|
||||
arcfour.c \
|
||||
arcfive.c \
|
||||
desblapi.c \
|
||||
des.c \
|
||||
rijndael.c \
|
||||
aeskeywrap.c \
|
||||
dh.c \
|
||||
ec.c \
|
||||
pqg.c \
|
||||
dsa.c \
|
||||
rsa.c \
|
||||
shvfy.c \
|
||||
$(MPI_SRCS) \
|
||||
$(ECL_SRCS) \
|
||||
$(NULL)
|
||||
|
||||
ALL_CSRCS := $(CSRCS)
|
||||
|
||||
ALL_HDRS = \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
des.h \
|
||||
ec.h \
|
||||
loader.h \
|
||||
rijndael.h \
|
||||
secmpi.h \
|
||||
sha.h \
|
||||
sha_fast.h \
|
||||
shsign.h \
|
||||
vis_proto.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
DEFINES += -DNSS_ENABLE_ECC
|
||||
endif
|
||||
|
||||
ifdef AES_GEN_TBL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES
|
||||
else
|
||||
ifdef AES_GEN_TBL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
|
||||
else
|
||||
ifdef AES_GEN_VAL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES
|
||||
else
|
||||
ifdef AES_GEN_VAL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
|
||||
else
|
||||
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,278 +0,0 @@
|
||||
#
|
||||
# Makefile for MPI library
|
||||
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
#
|
||||
# $Id: Makefile,v 1.21 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
include target.mk
|
||||
|
||||
CFLAGS+= $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \
|
||||
mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
|
||||
basecvt fact exptmod pi makeprime identest
|
||||
|
||||
LIBOBJS = mpprime.o mpmontg.o mplogic.o mp_gf2m.o mpi.o $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mp_gf2m.h mpprime.h
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libmpi.a - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#.c.o: $*.h $*.c
|
||||
# $(CC) $(CFLAGS) -c $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.o: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS)
|
||||
|
||||
mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.o: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.o: mpi_mips.s
|
||||
$(CC) -o $@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi_sparc.o : montmulf.h
|
||||
|
||||
mpv_sparcv9.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_64.il mpv_sparc.c
|
||||
|
||||
mpv_sparcv8.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_32.il mpv_sparc.c
|
||||
|
||||
montmulfv8.o montmulfv9.o mpv_sparcv8.o mpv_sparcv9.o : %.o : %.s
|
||||
$(CC) -o $@ $(SOLARIS_ASM_FLAGS) -c $<
|
||||
|
||||
# This rule is used to build the .s sources, which are then hand optimized.
|
||||
#montmulfv8.s montmulfv9.s : montmulf%.s : montmulf%.il montmulf.c montmulf.h
|
||||
# $(CC) -o $@ $(SOLARIS_ASM_FLAGS) -S montmulf$*.il montmulf.c
|
||||
|
||||
|
||||
libmpi.a: $(LIBOBJS)
|
||||
ar -cvr libmpi.a $(LIBOBJS)
|
||||
$(RANLIB) libmpi.a
|
||||
|
||||
lib libs: libmpi.a
|
||||
|
||||
mpi.i: mpi.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
|
||||
mptest4b.o mptest6.o mptest7.o mptest8.o mptest9.o mptestb.o
|
||||
MPTESTS = $(MPTESTOBJS:.o=)
|
||||
|
||||
$(MPTESTOBJS): mptest%.o: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%: mptest%.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b mptest6 \
|
||||
mptestb bbsrand
|
||||
|
||||
utests: mptest7 mptest8 mptest9
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.o bbs_rand.o prng.o
|
||||
UTILOBJS = primegen.o metime.o identest.o basecvt.o fact.o exptmod.o pi.o \
|
||||
makeprime.o gcd.o invmod.o lap.o isprime.o \
|
||||
dec2hex.o hex2dec.o
|
||||
UTILS = $(UTILOBJS:.o=)
|
||||
|
||||
$(UTILS): % : %.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.o : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
prng: prng.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
bbsrand: bbsrand.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
utils: $(UTILS) prng bbsrand
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.o: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
mpi-test: mpi-test.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mdxptest.o: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest: mdxptest.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mulsqr.o: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o $@ -c mulsqr.c
|
||||
|
||||
mulsqr: mulsqr.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f utils/*.o
|
||||
rm -f utils/core
|
||||
rm -f utils/*~ utils/.*~
|
||||
|
||||
clobber: clean
|
||||
rm -f $(TOOLS) $(UTILS)
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f libmpi.a
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
# END
|
||||
@@ -1,280 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with VACPP on OS/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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.os2,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=icc.exe
|
||||
AS=alp.exe
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
|
||||
#OS/2
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = /Ti+ -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
$(MPICMN)
|
||||
ASFLAGS =
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test.exe - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ilib /out:mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,280 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with MSVC on NT
|
||||
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.win,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=cl.exe
|
||||
AS=ml.exe
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
|
||||
|
||||
#NT
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = -O2 -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
ASFLAGS = -Cp -Sn -Zi -coff -I.
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) -c $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ar -cvr mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,799 +0,0 @@
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1997-2000
|
||||
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 *****
|
||||
|
||||
About the MPI Library
|
||||
---------------------
|
||||
|
||||
The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision
|
||||
signed integer arithmetic package. The implementation is not the most
|
||||
efficient possible, but the code is small and should be fairly easily
|
||||
portable to just about any machine that supports an ANSI C compiler,
|
||||
as long as it is capable of at least 16-bit arithmetic (but also see
|
||||
below for more on this).
|
||||
|
||||
This library was written with an eye to cryptographic applications;
|
||||
thus, some care is taken to make sure that temporary values are not
|
||||
left lying around in memory when they are no longer in use. This adds
|
||||
some overhead for zeroing buffers before they are released back into
|
||||
the free pool; however, it gives you the assurance that there is only
|
||||
one copy of your important values residing in your process's address
|
||||
space at a time. Obviously, it is difficult to guarantee anything, in
|
||||
a pre-emptive multitasking environment, but this at least helps you
|
||||
keep a lid on the more obvious ways your data can get spread around in
|
||||
memory.
|
||||
|
||||
|
||||
Using the Library
|
||||
-----------------
|
||||
|
||||
To use the MPI library in your program, you must include the header:
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
This header provides all the type and function declarations you'll
|
||||
need to use the library. Almost all the names defined by the library
|
||||
begin with the prefix 'mp_', so it should be easy to keep them from
|
||||
clashing with your program's namespace (he says, glibly, knowing full
|
||||
well there are always pathological cases).
|
||||
|
||||
There are a few things you may want to configure about the library.
|
||||
By default, the MPI library uses an unsigned short for its digit type,
|
||||
and an unsigned int for its word type. The word type must be big
|
||||
enough to contain at least two digits, for the primitive arithmetic to
|
||||
work out. On my machine, a short is 2 bytes and an int is 4 bytes --
|
||||
but if you have 64-bit ints, you might want to use a 4-byte digit and
|
||||
an 8-byte word. I have tested the library using 1-byte digits and
|
||||
2-byte words, as well. Whatever you choose to do, the things you need
|
||||
to change are:
|
||||
|
||||
(1) The type definitions for mp_digit and mp_word.
|
||||
|
||||
(2) The macro DIGIT_FMT which tells mp_print() how to display a
|
||||
single digit. This is just a printf() format string, so you
|
||||
can adjust it appropriately.
|
||||
|
||||
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
|
||||
largest value expressible in an mp_digit and an mp_word,
|
||||
respectively.
|
||||
|
||||
Both the mp_digit and mp_word should be UNSIGNED integer types. The
|
||||
code relies on having the full positive precision of the type used for
|
||||
digits and words.
|
||||
|
||||
The remaining type definitions should be left alone, for the most
|
||||
part. The code in the library does not make any significant
|
||||
assumptions about the sizes of things, but there is little if any
|
||||
reason to change the other parameters, so I would recommend you leave
|
||||
them as you found them.
|
||||
|
||||
The library comes with a Perl script, 'types.pl', which will scan your
|
||||
current Makefile settings, and attempt to find good definitions for
|
||||
these types. It relies on a Unix sort of build environment, so it
|
||||
probably won't work under MacOS or Windows, but it can be convenient
|
||||
if you're porting to a new flavour of Unix. Just run 'types.pl' at
|
||||
the command line, and it will spit out its results to the standard
|
||||
output.
|
||||
|
||||
|
||||
Conventions
|
||||
-----------
|
||||
|
||||
Most functions in the library return a value of type mp_err. This
|
||||
permits the library to communicate success or various kinds of failure
|
||||
to the calling program. The return values currently defined are:
|
||||
|
||||
MP_OKAY - okay, operation succeeded, all's well
|
||||
MP_YES - okay, the answer is yes (same as MP_OKAY)
|
||||
MP_NO - okay, but answer is no (not MP_OKAY)
|
||||
MP_MEM - operation ran out of memory
|
||||
MP_RANGE - input parameter was out of range
|
||||
MP_BADARG - an invalid input parameter was provided
|
||||
MP_UNDEF - no output value is defined for this input
|
||||
|
||||
The only function which currently uses MP_UNDEF is mp_invmod().
|
||||
Division by zero is undefined, but the division functions will return
|
||||
MP_RANGE for a zero divisor. MP_BADARG usually means you passed a
|
||||
bogus mp_int structure to the function. MP_YES and MP_NO are not used
|
||||
by the library itself; they're defined so you can use them in your own
|
||||
extensions.
|
||||
|
||||
If you need a readable interpretation of these error codes in your
|
||||
program, you may also use the mp_strerror() function. This function
|
||||
takes an mp_err as input, and returns a pointer to a human-readable
|
||||
string describing the meaning of the error. These strings are stored
|
||||
as constants within the library, so the caller should not attempt to
|
||||
modify or free the memory associated with these strings.
|
||||
|
||||
The library represents values in signed-magnitude format. Values
|
||||
strictly less than zero are negative, all others are considered
|
||||
positive (zero is positive by fiat). You can access the 'sign' member
|
||||
of the mp_int structure directly, but better is to use the mp_cmp_z()
|
||||
function, to find out which side of zero the value lies on.
|
||||
|
||||
Most arithmetic functions have a single-digit variant, as well as the
|
||||
full arbitrary-precision. An mp_digit is an unsigned value between 0
|
||||
and DIGIT_MAX inclusive. The radix is available as RADIX. The number
|
||||
of bits in a given digit is given as DIGIT_BIT.
|
||||
|
||||
Generally, input parameters are given before output parameters.
|
||||
Unless otherwise specified, any input parameter can be re-used as an
|
||||
output parameter, without confusing anything.
|
||||
|
||||
The basic numeric type defined by the library is an mp_int. Virtually
|
||||
all the functions in the library take a pointer to an mp_int as one of
|
||||
their parameters. An explanation of how to create and use these
|
||||
<HR>
|
||||
<A NAME="p23">
|
||||
<H3>Problem 23:</H3>
|
||||
|
||||
structures follows. And so, without further ado...
|
||||
|
||||
|
||||
Initialization and Cleanup
|
||||
--------------------------
|
||||
|
||||
The basic numeric type defined by the library is an 'mp_int'.
|
||||
However, it is not sufficient to simply declare a variable of type
|
||||
mp_int in your program. These variables also need to be initialized
|
||||
before they can be used, to allocate the internal storage they require
|
||||
for computation.
|
||||
|
||||
This is done using one of the following functions:
|
||||
|
||||
mp_init(mp_int *mp);
|
||||
mp_init_copy(mp_int *mp, mp_int *from);
|
||||
mp_init_size(mp_int *mp, mp_size p);
|
||||
|
||||
Each of these requires a pointer to a structure of type mp_int. The
|
||||
basic mp_init() simply initializes the mp_int to a default size, and
|
||||
sets its value to zero. If you would like to initialize a copy of an
|
||||
existing mp_int, use mp_init_copy(), where the 'from' parameter is the
|
||||
mp_int you'd like to make a copy of. The third function,
|
||||
mp_init_size(), permits you to specify how many digits of precision
|
||||
should be preallocated for your mp_int. This can help the library
|
||||
avoid unnecessary re-allocations later on.
|
||||
|
||||
The default precision used by mp_init() can be retrieved using:
|
||||
|
||||
precision = mp_get_prec();
|
||||
|
||||
This returns the number of digits that will be allocated. You can
|
||||
change this value by using:
|
||||
|
||||
mp_set_prec(unsigned int prec);
|
||||
|
||||
Any positive value is acceptable -- if you pass zero, the default
|
||||
precision will be re-set to the compiled-in library default (this is
|
||||
specified in the header file 'mpi-config.h', and typically defaults to
|
||||
8 or 16).
|
||||
|
||||
Just as you must allocate an mp_int before you can use it, you must
|
||||
clean up the structure when you are done with it. This is performed
|
||||
using the mp_clear() function. Remember that any mp_int that you
|
||||
create as a local variable in a function must be mp_clear()'d before
|
||||
that function exits, or else the memory allocated to that mp_int will
|
||||
be orphaned and unrecoverable.
|
||||
|
||||
To set an mp_int to a given value, the following functions are given:
|
||||
|
||||
mp_set(mp_int *mp, mp_digit d);
|
||||
mp_set_int(mp_int *mp, long z);
|
||||
|
||||
The mp_set() function sets the mp_int to a single digit value, while
|
||||
mp_set_int() sets the mp_int to a signed long integer value.
|
||||
|
||||
To set an mp_int to zero, use:
|
||||
|
||||
mp_zero(mp_int *mp);
|
||||
|
||||
|
||||
Copying and Moving
|
||||
------------------
|
||||
|
||||
If you have two initialized mp_int's, and you want to copy the value
|
||||
of one into the other, use:
|
||||
|
||||
mp_copy(from, to)
|
||||
|
||||
This takes care of clearing the old value of 'to', and copies the new
|
||||
value into it. If 'to' is not yet initialized, use mp_init_copy()
|
||||
instead (see above).
|
||||
|
||||
Note: The library tries, whenever possible, to avoid allocating
|
||||
---- new memory. Thus, mp_copy() tries first to satisfy the needs
|
||||
of the copy by re-using the memory already allocated to 'to'.
|
||||
Only if this proves insufficient will mp_copy() actually
|
||||
allocate new memory.
|
||||
|
||||
For this reason, if you know a priori that 'to' has enough
|
||||
available space to hold 'from', you don't need to check the
|
||||
return value of mp_copy() for memory failure. The USED()
|
||||
macro tells you how many digits are used by an mp_int, and
|
||||
the ALLOC() macro tells you how many are allocated.
|
||||
|
||||
If you have two initialized mp_int's, and you want to exchange their
|
||||
values, use:
|
||||
|
||||
mp_exch(a, b)
|
||||
|
||||
This is better than using mp_copy() with a temporary, since it will
|
||||
not (ever) touch the memory allocator -- it just swaps the exact
|
||||
contents of the two structures. The mp_exch() function cannot fail;
|
||||
if you pass it an invalid structure, it just ignores it, and does
|
||||
nothing.
|
||||
|
||||
|
||||
Basic Arithmetic
|
||||
----------------
|
||||
|
||||
Once you have initialized your integers, you can operate on them. The
|
||||
basic arithmetic functions on full mp_int values are:
|
||||
|
||||
mp_add(a, b, c) - computes c = a + b
|
||||
mp_sub(a, b, c) - computes c = a - b
|
||||
mp_mul(a, b, c) - computes c = a * b
|
||||
mp_sqr(a, b) - computes b = a * a
|
||||
mp_div(a, b, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d
|
||||
mp_expt(a, b, c) - computes c = a ** b
|
||||
mp_2expt(a, k) - computes a = 2^k
|
||||
mp_sqrt(a, c) - computes c = floor(sqrt(a))
|
||||
|
||||
The mp_div_2d() function efficiently computes division by powers of
|
||||
two. Either the q or r parameter may be NULL, in which case that
|
||||
portion of the computation will be discarded.
|
||||
|
||||
The algorithms used for some of the computations here are described in
|
||||
the following files which are included with this distribution:
|
||||
|
||||
mul.txt Describes the multiplication algorithm
|
||||
div.txt Describes the division algorithm
|
||||
expt.txt Describes the exponentiation algorithm
|
||||
sqrt.txt Describes the square-root algorithm
|
||||
square.txt Describes the squaring algorithm
|
||||
|
||||
There are single-digit versions of most of these routines, as well.
|
||||
In the following prototypes, 'd' is a single mp_digit:
|
||||
|
||||
mp_add_d(a, d, c) - computes c = a + d
|
||||
mp_sub_d(a, d, c) - computes c = a - d
|
||||
mp_mul_d(a, d, c) - computes c = a * d
|
||||
mp_mul_2(a, c) - computes c = a * 2
|
||||
mp_div_d(a, d, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2(a, c) - computes c = a / 2
|
||||
mp_expt_d(a, d, c) - computes c = a ** d
|
||||
|
||||
The mp_mul_2() and mp_div_2() functions take advantage of the internal
|
||||
representation of an mp_int to do multiplication by two more quickly
|
||||
than mp_mul_d() would. Other basic functions of an arithmetic variety
|
||||
include:
|
||||
|
||||
mp_zero(a) - assign 0 to a
|
||||
mp_neg(a, c) - negate a: c = -a
|
||||
mp_abs(a, c) - absolute value: c = |a|
|
||||
|
||||
|
||||
Comparisons
|
||||
-----------
|
||||
|
||||
Several comparison functions are provided. Each of these, unless
|
||||
otherwise specified, returns zero if the comparands are equal, < 0 if
|
||||
the first is less than the second, and > 0 if the first is greater
|
||||
than the second:
|
||||
|
||||
mp_cmp_z(a) - compare a <=> 0
|
||||
mp_cmp_d(a, d) - compare a <=> d, d is a single digit
|
||||
mp_cmp(a, b) - compare a <=> b
|
||||
mp_cmp_mag(a, b) - compare |a| <=> |b|
|
||||
mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer
|
||||
mp_isodd(a) - return nonzero if odd, zero otherwise
|
||||
mp_iseven(a) - return nonzero if even, zero otherwise
|
||||
|
||||
|
||||
Modular Arithmetic
|
||||
------------------
|
||||
|
||||
Modular variations of the basic arithmetic functions are also
|
||||
supported. These are available if the MP_MODARITH parameter in
|
||||
mpi-config.h is turned on (it is by default). The modular arithmetic
|
||||
functions are:
|
||||
|
||||
mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m
|
||||
mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below)
|
||||
mp_addmod(a, b, m, c) - compute c = (a + b) mod m
|
||||
mp_submod(a, b, m, c) - compute c = (a - b) mod m
|
||||
mp_mulmod(a, b, m, c) - compute c = (a * b) mod m
|
||||
mp_sqrmod(a, m, c) - compute c = (a * a) mod m
|
||||
mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m
|
||||
mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m
|
||||
|
||||
The mp_sqr() function squares its input argument. A call to mp_sqr(a,
|
||||
c) is identical in meaning to mp_mul(a, a, c); however, if the
|
||||
MP_SQUARE variable is set true in mpi-config.h (see below), then it
|
||||
will be implemented with a different algorithm, that is supposed to
|
||||
take advantage of the redundant computation that takes place during
|
||||
squaring. Unfortunately, some compilers result in worse performance
|
||||
on this code, so you can change the behaviour at will. There is a
|
||||
utility program "mulsqr.c" that lets you test which does better on
|
||||
your system.
|
||||
|
||||
The mp_sqrmod() function is analogous to the mp_sqr() function; it
|
||||
uses the mp_sqr() function rather than mp_mul(), and then performs the
|
||||
modular reduction. This probably won't help much unless you are doing
|
||||
a lot of them.
|
||||
|
||||
See the file 'square.txt' for a synopsis of the algorithm used.
|
||||
|
||||
Note: The mp_mod_d() function computes a modular reduction around
|
||||
---- a single digit d. The result is a single digit c.
|
||||
|
||||
Because an inverse is defined for a (mod m) if and only if (a, m) = 1
|
||||
(that is, if a and m are relatively prime), mp_invmod() may not be
|
||||
able to compute an inverse for the arguments. In this case, it
|
||||
returns the value MP_UNDEF, and does not modify c. If an inverse is
|
||||
defined, however, it returns MP_OKAY, and sets c to the value of the
|
||||
inverse (mod m).
|
||||
|
||||
See the file 'redux.txt' for a description of the modular reduction
|
||||
algorithm used by mp_exptmod().
|
||||
|
||||
|
||||
Greatest Common Divisor
|
||||
-----------------------
|
||||
|
||||
If The greates common divisor of two values can be found using one of the
|
||||
following functions:
|
||||
|
||||
mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm
|
||||
mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b)
|
||||
mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b)
|
||||
|
||||
Also provided is a function to compute modular inverses, if they
|
||||
exist:
|
||||
|
||||
mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists
|
||||
|
||||
The function mp_xgcd() computes the greatest common divisor, and also
|
||||
returns values of x and y satisfying Bezout's identity. This is used
|
||||
by mp_invmod() to find modular inverses. However, if you do not need
|
||||
these values, you will find that mp_gcd() is MUCH more efficient,
|
||||
since it doesn't need all the intermediate values that mp_xgcd()
|
||||
requires in order to compute x and y.
|
||||
|
||||
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
|
||||
algorithm due to Josef Stein.
|
||||
|
||||
|
||||
Input & Output Functions
|
||||
------------------------
|
||||
|
||||
The following basic I/O routines are provided. These are present at
|
||||
all times:
|
||||
|
||||
mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
|
||||
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
|
||||
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
|
||||
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
|
||||
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
|
||||
digits
|
||||
mp_toraw(mp, str) - convert an mp_int to a string of bytes
|
||||
mp_tovalue(ch, r) - convert ch to its value when taken as
|
||||
a radix r digit, or -1 if invalid
|
||||
mp_strerror(err) - get a string describing mp_err value 'err'
|
||||
|
||||
If you compile the MPI library with MP_IOFUNC defined, you will also
|
||||
have access to the following additional I/O function:
|
||||
|
||||
mp_print(mp, ofp) - print an mp_int as text to output stream ofp
|
||||
|
||||
Note that mp_radix_size() returns a size in bytes guaranteed to be AT
|
||||
LEAST big enough for the digits output by mp_toradix(). Because it
|
||||
uses an approximation technique to figure out how many digits will be
|
||||
needed, it may return a figure which is larger than necessary. Thus,
|
||||
the caller should not rely on the value to determine how many bytes
|
||||
will actually be written by mp_toradix(). The string mp_toradix()
|
||||
creates will be NUL terminated, so the standard C library function
|
||||
strlen() should be able to ascertain this for you, if you need it.
|
||||
|
||||
The mp_read_radix() and mp_toradix() functions support bases from 2 to
|
||||
64 inclusive. If you require more general radix conversion facilities
|
||||
than this, you will need to write them yourself (that's why mp_div_d()
|
||||
is provided, after all).
|
||||
|
||||
Note: mp_read_radix() will accept as digits either capital or
|
||||
---- lower-case letters. However, the current implementation of
|
||||
mp_toradix() only outputs upper-case letters, when writing
|
||||
bases betwee 10 and 36. The underlying code supports using
|
||||
lower-case letters, but the interface stub does not have a
|
||||
selector for it. You can add one yourself if you think it
|
||||
is worthwhile -- I do not. Bases from 36 to 64 use lower-
|
||||
case letters as distinct from upper-case. Bases 63 and
|
||||
64 use the characters '+' and '/' as digits.
|
||||
|
||||
Note also that compiling with MP_IOFUNC defined will cause
|
||||
inclusion of <stdio.h>, so if you are trying to write code
|
||||
which does not depend on the standard C library, you will
|
||||
probably want to avoid this option. This is needed because
|
||||
the mp_print() function takes a standard library FILE * as
|
||||
one of its parameters, and uses the fprintf() function.
|
||||
|
||||
The mp_toraw() function converts the integer to a sequence of bytes,
|
||||
in big-endian ordering (most-significant byte first). Assuming your
|
||||
bytes are 8 bits wide, this corresponds to base 256. The sign is
|
||||
encoded as a single leading byte, whose value is 0 for zero or
|
||||
positive values, or 1 for negative values. The mp_read_raw() function
|
||||
reverses this process -- it takes a buffer of bytes, interprets the
|
||||
first as a sign indicator (0 = zero/positive, nonzero = negative), and
|
||||
the rest as a sequence of 1-byte digits in big-endian ordering.
|
||||
|
||||
The mp_raw_size() function returns the exact number of bytes required
|
||||
to store the given integer in "raw" format (as described in the
|
||||
previous paragraph). Zero is returned in case of error; a valid
|
||||
integer will require at least three bytes of storage.
|
||||
|
||||
In previous versions of the MPI library, an "external representation
|
||||
format" was supported. This was removed, however, because I found I
|
||||
was never using it, it was not as portable as I would have liked, and
|
||||
I decided it was a waste of space.
|
||||
|
||||
|
||||
Other Functions
|
||||
---------------
|
||||
|
||||
The files 'mpprime.h' and 'mpprime.c' define some routines which are
|
||||
useful for divisibility testing and probabilistic primality testing.
|
||||
The routines defined are:
|
||||
|
||||
mpp_divis(a, b) - is a divisible by b?
|
||||
mpp_divis_d(a, d) - is a divisible by digit d?
|
||||
mpp_random(a) - set a to random value at current precision
|
||||
mpp_random_size(a, prec) - set a to random value at given precision
|
||||
|
||||
Note: The mpp_random() and mpp_random_size() functions use the C
|
||||
---- library's rand() function to generate random values. It is
|
||||
up to the caller to seed this generator before it is called.
|
||||
These functions are not suitable for generating quantities
|
||||
requiring cryptographic-quality randomness; they are intended
|
||||
primarily for use in primality testing.
|
||||
|
||||
Note too that the MPI library does not call srand(), so your
|
||||
application should do this, if you ever want the sequence
|
||||
to change.
|
||||
|
||||
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
|
||||
in v? If so, let w be the index of
|
||||
that digit
|
||||
|
||||
mpp_divis_primes(a, np) - is a divisible by any of the first np
|
||||
primes? If so, set np to the prime
|
||||
which divided a.
|
||||
|
||||
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
|
||||
returns MP_YES, otherwise MP_NO.
|
||||
|
||||
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
|
||||
Miller probabilistic primality test
|
||||
on a. Returns MP_YES if all tests
|
||||
passed, or MP_NO if any test fails.
|
||||
|
||||
The mpp_fermat() function works based on Fermat's little theorem, a
|
||||
consequence of which is that if p is a prime, and (w, p) = 1, then:
|
||||
|
||||
w^p = w (mod p)
|
||||
|
||||
Put another way, if w^p != w (mod p), then p is not prime. The test
|
||||
is expensive to compute, but it helps to quickly eliminate an enormous
|
||||
class of composite numbers prior to Rabin-Miller testing.
|
||||
|
||||
Building the Library
|
||||
--------------------
|
||||
|
||||
The MPI library is designed to be as self-contained as possible. You
|
||||
should be able to compile it with your favourite ANSI C compiler, and
|
||||
link it into your program directly. If you are on a Unix system using
|
||||
the GNU C compiler (gcc), the following should work:
|
||||
|
||||
% gcc -ansi -pedantic -Wall -O2 -c mpi.c
|
||||
|
||||
The file 'mpi-config.h' defines several configurable parameters for
|
||||
the library, which you can adjust to suit your application. At the
|
||||
time of this writing, the available options are:
|
||||
|
||||
MP_IOFUNC - Define true to include the mp_print() function,
|
||||
which is moderately useful for debugging. This
|
||||
implicitly includes <stdio.h>.
|
||||
|
||||
MP_MODARITH - Define true to include the modular arithmetic
|
||||
functions. If you don't need modular arithmetic
|
||||
in your application, you can set this to zero to
|
||||
leave out all the modular routines.
|
||||
|
||||
MP_NUMTH - Define true to include number theoretic functions
|
||||
such as mp_gcd(), mp_lcm(), and mp_invmod().
|
||||
|
||||
MP_LOGTAB - If true, the file "logtab.h" is included, which
|
||||
is basically a static table of base 2 logarithms.
|
||||
These are used to compute how big the buffers for
|
||||
radix conversion need to be. If you set this false,
|
||||
the library includes <math.h> and uses log(). This
|
||||
typically forces you to link against math libraries.
|
||||
|
||||
MP_MEMSET - If true, use memset() to zero buffers. If you run
|
||||
into weird alignment related bugs, set this to zero
|
||||
and an explicit loop will be used.
|
||||
|
||||
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
|
||||
into weird alignment bugs, set this to zero and an
|
||||
explicit loop will be used.
|
||||
|
||||
MP_CRYPTO - If true, whenever arrays of digits are free'd, they
|
||||
are zeroed first. This is useful if you're using
|
||||
the library in a cryptographic environment; however,
|
||||
it does add overhead to each free operation. For
|
||||
performance, if you don't care about zeroing your
|
||||
buffers, set this to false.
|
||||
|
||||
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
|
||||
checking macro, ARGCHK(), gets expanded. If this
|
||||
is set to zero, ARGCHK() expands to nothing; no
|
||||
argument checks are performed. If this is 1, the
|
||||
ARGCHK() macro expands to code that returns MP_BADARG
|
||||
or similar at runtime. If it is 2, ARGCHK() expands
|
||||
to an assert() call that aborts the program on a
|
||||
bad input.
|
||||
|
||||
MP_DEBUG - Turns on debugging output. This is probably not at
|
||||
all useful unless you are debugging the library. It
|
||||
tends to spit out a LOT of output.
|
||||
|
||||
MP_DEFPREC - The default precision of a newly-created mp_int, in
|
||||
digits. The precision can be changed at runtime by
|
||||
the mp_set_prec() function, but this is its initial
|
||||
value.
|
||||
|
||||
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
|
||||
function will use an alternate algorithm that takes
|
||||
advantage of the redundant inner product computation
|
||||
when both multiplicands are identical. Unfortunately,
|
||||
with some compilers this is actually SLOWER than just
|
||||
calling mp_mul() with the same argument twice. So
|
||||
if you set MP_SQUARE to zero, mp_sqr() will be expan-
|
||||
ded into a call to mp_mul(). This applies to all
|
||||
the uses of mp_sqr(), including mp_sqrmod() and the
|
||||
internal calls to s_mp_sqr() inside mpi.c
|
||||
|
||||
The program 'mulsqr' (mulsqr.c) can be used to test
|
||||
which works best for your configuration. Set up the
|
||||
CC and CFLAGS variables in the Makefile, then type:
|
||||
|
||||
make mulsqr
|
||||
|
||||
Invoke it with arguments similar to the following:
|
||||
|
||||
mulsqr 25000 1024
|
||||
|
||||
That is, 25000 products computed on 1024-bit values.
|
||||
The output will compare the two timings, and recommend
|
||||
a setting for MP_SQUARE. It is off by default.
|
||||
|
||||
If you would like to use the mp_print() function (see above), be sure
|
||||
to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the
|
||||
'tests' subdirectory expect this to be defined (although the test
|
||||
driver 'mpi-test' doesn't need it)
|
||||
|
||||
The Makefile which comes with the library should take care of building
|
||||
the library for you, if you have set the CC and CFLAGS variables at
|
||||
the top of the file appropriately. By default, they are set up to
|
||||
use the GNU C compiler:
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-ansi -pedantic -Wall -O2
|
||||
|
||||
If all goes well, the library should compile without warnings using
|
||||
this combination. You should, of course, make whatever adjustments
|
||||
you find necessary.
|
||||
|
||||
The MPI library distribution comes with several additional programs
|
||||
which are intended to demonstrate the use of the library, and provide
|
||||
a framework for testing it. There are a handful of test driver
|
||||
programs, in the files named 'mptest-X.c', where X is a digit. Also,
|
||||
there are some simple command-line utilities (in the 'utils'
|
||||
directory) for manipulating large numbers. These include:
|
||||
|
||||
basecvt.c A radix-conversion program, supporting bases from
|
||||
2 to 64 inclusive.
|
||||
|
||||
bbsrand.c A BBS (quadratic residue) pseudo-random number
|
||||
generator. The file 'bbsrand.c' is just the driver
|
||||
for the program; the real code lives in the files
|
||||
'bbs_rand.h' and 'bbs_rand.c'
|
||||
|
||||
dec2hex.c Converts decimal to hexadecimal
|
||||
|
||||
gcd.c Computes the greatest common divisor of two values.
|
||||
If invoked as 'xgcd', also computes constants x and
|
||||
y such that (a, b) = ax + by, in accordance with
|
||||
Bezout's identity.
|
||||
|
||||
hex2dec.c Converts hexadecimal to decimal
|
||||
|
||||
invmod.c Computes modular inverses
|
||||
|
||||
isprime.c Performs the Rabin-Miller probabilistic primality
|
||||
test on a number. Values which fail this test are
|
||||
definitely composite, and those which pass are very
|
||||
likely to be prime (although there are no guarantees)
|
||||
|
||||
lap.c Computes the order (least annihilating power) of
|
||||
a value v modulo m. Very dumb algorithm.
|
||||
|
||||
primegen.c Generates large (probable) primes.
|
||||
|
||||
prng.c A pseudo-random number generator based on the
|
||||
BBS generator code in 'bbs_rand.c'
|
||||
|
||||
sieve.c Implements the Sieve of Eratosthenes, using a big
|
||||
bitmap, to generate a list of prime numbers.
|
||||
|
||||
fact.c Computes the factorial of an arbitrary precision
|
||||
integer (iterative).
|
||||
|
||||
exptmod.c Computes arbitrary precision modular exponentiation
|
||||
from the command line (exptmod a b m -> a^b (mod m))
|
||||
|
||||
Most of these can be built from the Makefile that comes with the
|
||||
library. Try 'make tools', if your environment supports it. (If you
|
||||
are compiling on a Macintosh, I'm afraid you'll have to build them by
|
||||
hand -- fortunately, this is not difficult -- the library itself
|
||||
should compile just fine under Metrowerks CodeWarrior).
|
||||
|
||||
|
||||
Testing the Library
|
||||
-------------------
|
||||
|
||||
Automatic test vectors are included, in the form of a program called
|
||||
'mpi-test'. To build this program and run all the tests, simply
|
||||
invoke the shell script 'all-tests'. If all the tests pass, you
|
||||
should see a message:
|
||||
|
||||
All tests passed
|
||||
|
||||
If something went wrong, you'll get:
|
||||
|
||||
One or more tests failed.
|
||||
|
||||
If this happens, scan back through the preceding lines, to see which
|
||||
test failed. Any failure indicates a bug in the library, which needs
|
||||
to be fixed before it will give accurate results. If you get any such
|
||||
thing, please let me know, and I'll try to fix it. Please let me know
|
||||
what platform and compiler you were using, as well as which test
|
||||
failed. If a reason for failure was given, please send me that text
|
||||
as well.
|
||||
|
||||
If you're on a system such as the Macintosh, where the standard Unix
|
||||
build tools don't work, you can build the 'mpi-test' program manually,
|
||||
and run it by hand. This is tedious and obnoxious, sorry.
|
||||
|
||||
Further manual testing can be performed by building the manual testing
|
||||
programs, whose source is found in the 'tests' subdirectory. Each
|
||||
test is in a source file called 'mptest-X.c'. The Makefile contains a
|
||||
target to build all of them at once:
|
||||
|
||||
make tests
|
||||
|
||||
Read the comments at the top of each source file to see what the
|
||||
driver is supposed to test. You probably don't need to do this; these
|
||||
programs were only written to help me as I was developing the library.
|
||||
|
||||
The relevant files are:
|
||||
|
||||
mpi-test.c The source for the test driver
|
||||
|
||||
make-test-arrays A Perl script to generate some of the internal
|
||||
data structures used by mpi-test.c
|
||||
|
||||
test-arrays.txt The source file for make-test-arrays
|
||||
|
||||
all-tests A Bourne shell script which runs all the
|
||||
tests in the mpi-test suite
|
||||
|
||||
Running 'make mpi-test' should build the mpi-test program. If you
|
||||
cannot use make, here is what needs to be done:
|
||||
|
||||
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
|
||||
the 'test-arrays.txt' file. Since Perl can be found everywhere,
|
||||
even on the Macintosh, this should be no trouble. Under Unix,
|
||||
this looks like:
|
||||
|
||||
make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
(2) Build the MPI library:
|
||||
|
||||
gcc -ansi -pedantic -Wall -c mpi.c
|
||||
|
||||
(3) Build the mpi-test program:
|
||||
|
||||
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
|
||||
|
||||
When you've got mpi-test, you can use 'all-tests' to run all the tests
|
||||
made available by mpi-test. If any of them fail, there should be a
|
||||
diagnostic indicating what went wrong. These are fairly high-level
|
||||
diagnostics, and won't really help you debug the problem; they're
|
||||
simply intended to help you isolate which function caused the problem.
|
||||
If you encounter a problem of this sort, feel free to e-mail me, and I
|
||||
will certainly attempt to help you debug it.
|
||||
|
||||
Note: Several of the tests hard-wired into 'mpi-test' operate under
|
||||
---- the assumption that you are using at least a 16-bit mp_digit
|
||||
type. If that is not true, several tests might fail, because
|
||||
of range problems with the maximum digit value.
|
||||
|
||||
If you are using an 8-bit digit, you will also need to
|
||||
modify the code for mp_read_raw(), which assumes that
|
||||
multiplication by 256 can be done with mp_mul_d(), a
|
||||
fact that fails when DIGIT_MAX is 255. You can replace
|
||||
the call with s_mp_lshd(), which will give you the same
|
||||
effect, and without doing as much work. :)
|
||||
|
||||
Acknowledgements:
|
||||
----------------
|
||||
|
||||
The algorithms used in this library were drawn primarily from Volume
|
||||
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
|
||||
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
|
||||
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
|
||||
Cryptography_, Chapter 14.
|
||||
|
||||
Thanks are due to Tom St. Denis, for finding an obnoxious sign-related
|
||||
bug in mp_read_raw() that made things break on platforms which use
|
||||
signed chars.
|
||||
|
||||
About the Author
|
||||
----------------
|
||||
|
||||
This software was written by Michael J. Fromberger. You can contact
|
||||
the author as follows:
|
||||
|
||||
E-mail: <sting@linguist.dartmouth.edu>
|
||||
|
||||
Postal: 8000 Cummings Hall, Thayer School of Engineering
|
||||
Dartmouth College, Hanover, New Hampshire, USA
|
||||
|
||||
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
|
||||
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
|
||||
|
||||
Last updated: 16-Jan-2000
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1997
|
||||
# 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 *****
|
||||
|
||||
ECHO=/bin/echo
|
||||
MAKE=gmake
|
||||
|
||||
$ECHO "\n** Running unit tests for MPI library\n"
|
||||
|
||||
# Build the mpi-test program, which comprises all the unit tests for
|
||||
# the MPI library...
|
||||
|
||||
$ECHO "Bringing mpi-test up to date ... "
|
||||
if $MAKE mpi-test ; then
|
||||
:
|
||||
else
|
||||
$ECHO " "
|
||||
$ECHO "Make failed to build mpi-test."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x mpi-test ] ; then
|
||||
$ECHO " "
|
||||
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the list of available test suites...
|
||||
tests=`mpi-test list | awk '{print $1}'`
|
||||
errs=0
|
||||
|
||||
# Run each test suite and check the result code of mpi-test
|
||||
for test in $tests ; do
|
||||
$ECHO "$test ... \c"
|
||||
if mpi-test $test ; then
|
||||
$ECHO "passed"
|
||||
else
|
||||
$ECHO "FAILED"
|
||||
errs=1
|
||||
fi
|
||||
done
|
||||
|
||||
# If any tests failed, we'll stop at this point
|
||||
if [ "$errs" = "0" ] ; then
|
||||
$ECHO "All unit tests passed"
|
||||
else
|
||||
$ECHO "One or more tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now try to build the 'pi' program, and see if it can compute the
|
||||
# first thousand digits of pi correctly
|
||||
$ECHO "\n** Running other tests\n"
|
||||
|
||||
$ECHO "Bringing 'pi' up to date ... "
|
||||
if $MAKE pi ; then
|
||||
:
|
||||
else
|
||||
$ECHO "\nMake failed to build pi.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x pi ] ; then
|
||||
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./pi 2000 > /tmp/pi.tmp.$$
|
||||
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
|
||||
$ECHO "Okay! The pi test passes."
|
||||
else
|
||||
$ECHO "Oops! The pi test failed. :("
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f /tmp/pi.tmp.$$
|
||||
|
||||
exit 0
|
||||
|
||||
# Here there be dragons
|
||||
@@ -1,11 +0,0 @@
|
||||
Within this directory, each of the file listed below is licensed under
|
||||
the terms given in the file LICENSE-MPL, also in this directory.
|
||||
|
||||
basecvt.pod
|
||||
gcd.pod
|
||||
invmod.pod
|
||||
isprime.pod
|
||||
lap.pod
|
||||
mpi-test.pod
|
||||
prime.txt
|
||||
prng.pod
|
||||
@@ -1,32 +0,0 @@
|
||||
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 Netscape security libraries.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the
|
||||
terms of the GNU General Public License Version 2 or later (the
|
||||
"GPL"), in which case the provisions of the GPL are applicable
|
||||
instead of those above. If you wish to allow use of your
|
||||
version of this file only under the terms of the GPL and not to
|
||||
allow others to use your version of this file under the MPL,
|
||||
indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by
|
||||
the GPL. If you do not delete the provisions above, a recipient
|
||||
may use your version of this file under either the MPL or the
|
||||
GPL.
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
basecvt - radix conversion for arbitrary precision integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
basecvt <ibase> <obase> [values]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<basecvt> program is a command-line tool for converting integers
|
||||
of arbitrary precision from one radix to another. The current version
|
||||
supports radix values from 2 (binary) to 64, inclusive. The first two
|
||||
command line arguments specify the input and output radix, in base 10.
|
||||
Any further arguments are taken to be integers notated in the input
|
||||
radix, and these are converted to the output radix. The output is
|
||||
written, one integer per line, to standard output.
|
||||
|
||||
When reading integers, only digits considered "valid" for the input
|
||||
radix are considered. Processing of an integer terminates when an
|
||||
invalid input digit is encountered. So, for example, if you set the
|
||||
input radix to 10 and enter '10ACF', B<basecvt> would assume that you
|
||||
had entered '10' and ignore the rest of the string.
|
||||
|
||||
If no values are provided, no output is written, but the program
|
||||
simply terminates with a zero exit status. Error diagnostics are
|
||||
written to standard error in the event of out-of-range radix
|
||||
specifications. Regardless of the actual values of the input and
|
||||
output radix, the radix arguments are taken to be in base 10 (decimal)
|
||||
notation.
|
||||
|
||||
=head1 DIGITS
|
||||
|
||||
For radices from 2-10, standard ASCII decimal digits 0-9 are used for
|
||||
both input and output. For radices from 11-36, the ASCII letters A-Z
|
||||
are also included, following the convention used in hexadecimal. In
|
||||
this range, input is accepted in either upper or lower case, although
|
||||
on output only lower-case letters are used.
|
||||
|
||||
For radices from 37-62, the output includes both upper- and lower-case
|
||||
ASCII letters, and case matters. In this range, case is distinguished
|
||||
both for input and for output values.
|
||||
|
||||
For radices 63 and 64, the characters '+' (plus) and '/' (forward
|
||||
solidus) are also used. These are derived from the MIME base64
|
||||
encoding scheme. The overall encoding is not the same as base64,
|
||||
because the ASCII digits are used for the bottom of the range, and the
|
||||
letters are shifted upward; however, the output will consist of the
|
||||
same character set.
|
||||
|
||||
This input and output behaviour is inherited from the MPI library used
|
||||
by B<basecvt>, and so is not configurable at runtime.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
dec2hex(1), hex2dec(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:31 $
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
# $Id: build,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
VERS="1.7p6"
|
||||
SECT="1"
|
||||
NAME="MPI Tools"
|
||||
|
||||
echo "Building manual pages ..."
|
||||
case $# in
|
||||
0)
|
||||
files=`ls *.pod`
|
||||
;;
|
||||
*)
|
||||
files=$*
|
||||
;;
|
||||
esac
|
||||
|
||||
for name in $files
|
||||
do
|
||||
echo -n "$name ... "
|
||||
# sname=`noext $name`
|
||||
sname=`basename $name .pod`
|
||||
pod2man --section="$SECT" --center="$NAME" --release="$VERS" $name > $sname.$SECT
|
||||
echo "(done)"
|
||||
done
|
||||
|
||||
echo "Finished building."
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
Division
|
||||
|
||||
This describes the division algorithm used by the MPI library.
|
||||
|
||||
Input: a, b; a > b
|
||||
Compute: Q, R; a = Qb + R
|
||||
|
||||
The input numbers are normalized so that the high-order digit of b is
|
||||
at least half the radix. This guarantees that we have a reasonable
|
||||
way to guess at the digits of the quotient (this method was taken from
|
||||
Knuth, vol. 2, with adaptations).
|
||||
|
||||
To normalize, test the high-order digit of b. If it is less than half
|
||||
the radix, multiply both a and b by d, where:
|
||||
|
||||
radix - 1
|
||||
d = -----------
|
||||
bmax + 1
|
||||
|
||||
...where bmax is the high-order digit of b. Otherwise, set d = 1.
|
||||
|
||||
Given normalize values for a and b, let the notation a[n] denote the
|
||||
nth digit of a. Let #a be the number of significant figures of a (not
|
||||
including any leading zeroes).
|
||||
|
||||
Let R = 0
|
||||
Let p = #a - 1
|
||||
|
||||
while(p >= 0)
|
||||
do
|
||||
R = (R * radix) + a[p]
|
||||
p = p - 1
|
||||
while(R < b and p >= 0)
|
||||
|
||||
if(R < b)
|
||||
break
|
||||
|
||||
q = (R[#R - 1] * radix) + R[#R - 2]
|
||||
q = q / b[#b - 1]
|
||||
|
||||
T = b * q
|
||||
|
||||
while(T > L)
|
||||
q = q - 1
|
||||
T = T - b
|
||||
endwhile
|
||||
|
||||
L = L - T
|
||||
|
||||
Q = (Q * radix) + q
|
||||
|
||||
endwhile
|
||||
|
||||
At this point, Q is the quotient, and R is the normalized remainder.
|
||||
To denormalize R, compute:
|
||||
|
||||
R = (R / d)
|
||||
|
||||
At this point, you are finished.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: div.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
Exponentiation
|
||||
|
||||
For exponentiation, the MPI library uses a simple and fairly standard
|
||||
square-and-multiply method. The algorithm is this:
|
||||
|
||||
Input: a, b
|
||||
Output: a ** b
|
||||
|
||||
s = 1
|
||||
|
||||
while(b != 0)
|
||||
if(b is odd)
|
||||
s = s * a
|
||||
endif
|
||||
|
||||
b = b / 2
|
||||
|
||||
x = x * x
|
||||
endwhile
|
||||
|
||||
return s
|
||||
|
||||
The modular exponentiation is done the same way, except replacing:
|
||||
|
||||
s = s * a
|
||||
|
||||
with
|
||||
s = (s * a) mod m
|
||||
|
||||
and replacing
|
||||
|
||||
x = x * x
|
||||
|
||||
with
|
||||
|
||||
x = (x * x) mod m
|
||||
|
||||
Here is a sample exponentiation using the MPI library, as compared to
|
||||
the same problem solved by the Unix 'bc' program on my system:
|
||||
|
||||
Computation of 2,381,283 ** 235
|
||||
|
||||
'bc' says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
MPI says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
Diff says:
|
||||
% diff bc.txt mp.txt
|
||||
%
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: expt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
gcd - compute greatest common divisor of two integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
gcd <a> <b>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<gcd> program computes the greatest common divisor of two
|
||||
arbitrary-precision integers I<a> and I<b>. The result is written in
|
||||
standard decimal notation to the standard output.
|
||||
|
||||
If I<b> is zero, B<gcd> will print an error message and exit.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
invmod(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:32 $
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
invmod - compute modular inverse of an integer
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invmod <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<invmod> program computes the inverse of I<a>, modulo I<m>, if
|
||||
that inverse exists. Both I<a> and I<m> are arbitrary-precision
|
||||
integers in decimal notation. The result is written in standard
|
||||
decimal notation to the standard output.
|
||||
|
||||
If there is no inverse, the message:
|
||||
|
||||
No inverse
|
||||
|
||||
...will be printed to the standard output (an inverse exists if and
|
||||
only if the greatest common divisor of I<a> and I<m> is 1).
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
isprime - probabilistic primality testing
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
isprime <a>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<isprime> program attempts to determine whether the arbitrary
|
||||
precision integer I<a> is prime. It first tests I<a> for divisibility
|
||||
by the first 170 or so small primes, and assuming I<a> is not
|
||||
divisible by any of these, applies 15 iterations of the Rabin-Miller
|
||||
probabilistic primality test.
|
||||
|
||||
If the program discovers that the number is composite, it will print:
|
||||
|
||||
Not prime (reason)
|
||||
|
||||
Where I<reason> is either:
|
||||
|
||||
divisible by small prime x
|
||||
|
||||
Or:
|
||||
|
||||
failed nth pseudoprime test
|
||||
|
||||
In the first case, I<x> indicates the first small prime factor that
|
||||
was found. In the second case, I<n> indicates which of the
|
||||
pseudoprime tests failed (numbered from 1)
|
||||
|
||||
If this happens, the number is definitely not prime. However, if the
|
||||
number succeeds, this message results:
|
||||
|
||||
Probably prime, 1 in 4^15 chance of false positive
|
||||
|
||||
If this happens, the number is prime with very high probability, but
|
||||
its primality has not been absolutely proven, only demonstrated to a
|
||||
very convincing degree.
|
||||
|
||||
The value I<a> can be input in standard decimal notation, or, if it is
|
||||
prefixed with I<Ox>, it will be read as hexadecimal.
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
You can control how many iterations of Rabin-Miller are performed on
|
||||
the candidate number by setting the I<RM_TESTS> environment variable
|
||||
to an integer value before starting up B<isprime>. This will change
|
||||
the output slightly if the number passes all the tests.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
lap - compute least annihilating power of a number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
lap <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<lap> program computes the order of I<a> modulo I<m>, for
|
||||
arbitrary precision integers I<a> and I<m>. The B<order> of I<a>
|
||||
modulo I<m> is defined as the smallest positive value I<n> for which
|
||||
I<a> raised to the I<n>th power, modulo I<m>, is equal to 1. The
|
||||
order may not exist, if I<m> is composite.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
This program is very slow, especially for large moduli. It is
|
||||
intended as a way to help find primitive elements in a modular field,
|
||||
but it does not do so in a particularly inefficient manner. It was
|
||||
written simply to help verify that a particular candidate does not
|
||||
have an obviously short cycle mod I<m>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), isprime(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
mpi-test - automated test program for MPI library
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
mpi-test <suite-name> [quiet]
|
||||
mpi-test list
|
||||
mpi-test help
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<mpi-test> program is a general unit test driver for the MPI
|
||||
library. It is used to verify that the library works as it is
|
||||
supposed to on your architecture. As with most such things, passing
|
||||
all the tests in B<mpi-test> does not guarantee the code is correct,
|
||||
but if any of them fail, there are certainly problems.
|
||||
|
||||
Each major function of the library can be tested individually. For a
|
||||
list of the test suites understood by B<mpi-test>, run it with the
|
||||
I<list> command line option:
|
||||
|
||||
mpi-test list
|
||||
|
||||
This will display a list of the available test suites and a brief
|
||||
synopsis of what each one does. For a brief overview of this
|
||||
document, run B<mpi-test> I<help>.
|
||||
|
||||
B<mpi-test> exits with a zero status if the selected test succeeds, or
|
||||
a nonzero status if it fails. If a I<suite-name> which is not
|
||||
understood by B<mpi-test> is given, a diagnostic is printed to the
|
||||
standard error, and the program exits with a result code of 2. If a
|
||||
test fails, the result code will be 1, and a diagnostic is ordinarily
|
||||
printed to the standard error. However, if the I<quiet> option is
|
||||
provided, these diagnostics will be suppressed.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
Only a few canned test cases are provided. The solutions have been
|
||||
verified using the GNU bc(1) program, so bugs there may cause problems
|
||||
here; however, this is very unlikely, so if a test fails, it is almost
|
||||
certainly my fault, not bc(1)'s.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
@@ -1,114 +0,0 @@
|
||||
Multiplication
|
||||
|
||||
This describes the multiplication algorithm used by the MPI library.
|
||||
|
||||
This is basically a standard "schoolbook" algorithm. It is slow --
|
||||
O(mn) for m = #a, n = #b -- but easy to implement and verify.
|
||||
Basically, we run two nested loops, as illustrated here (R is the
|
||||
radix):
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#b - 1)
|
||||
for i <- 0 to (#a - 1)
|
||||
w = (a[j] * b[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
It is necessary that 'w' have room for at least two radix R digits.
|
||||
The product of any two digits in radix R is at most:
|
||||
|
||||
(R - 1)(R - 1) = R^2 - 2R + 1
|
||||
|
||||
Since a two-digit radix-R number can hold R^2 - 1 distinct values,
|
||||
this insures that the product will fit into the two-digit register.
|
||||
|
||||
To insure that two digits is enough for w, we must also show that
|
||||
there is room for the carry-in from the previous multiplication, and
|
||||
the current value of the product digit that is being recomputed.
|
||||
Assuming each of these may be as big as R - 1 (and no larger,
|
||||
certainly), two digits will be enough if and only if:
|
||||
|
||||
(R^2 - 2R + 1) + 2(R - 1) <= R^2 - 1
|
||||
|
||||
Solving this equation shows that, indeed, this is the case:
|
||||
|
||||
R^2 - 2R + 1 + 2R - 2 <= R^2 - 1
|
||||
|
||||
R^2 - 1 <= R^2 - 1
|
||||
|
||||
This suggests that a good radix would be one more than the largest
|
||||
value that can be held in half a machine word -- so, for example, as
|
||||
in this implementation, where we used a radix of 65536 on a machine
|
||||
with 4-byte words. Another advantage of a radix of this sort is that
|
||||
binary-level operations are easy on numbers in this representation.
|
||||
|
||||
Here's an example multiplication worked out longhand in radix-10,
|
||||
using the above algorithm:
|
||||
|
||||
a = 999
|
||||
b = x 999
|
||||
-------------
|
||||
p = 98001
|
||||
|
||||
w = (a[jx] * b[ix]) + kin + c[ix + jx]
|
||||
c[ix+jx] = w % RADIX
|
||||
k = w / RADIX
|
||||
product
|
||||
ix jx a[jx] b[ix] kin w c[i+j] kout 000000
|
||||
0 0 9 9 0 81+0+0 1 8 000001
|
||||
0 1 9 9 8 81+8+0 9 8 000091
|
||||
0 2 9 9 8 81+8+0 9 8 000991
|
||||
8 0 008991
|
||||
1 0 9 9 0 81+0+9 0 9 008901
|
||||
1 1 9 9 9 81+9+9 9 9 008901
|
||||
1 2 9 9 9 81+9+8 8 9 008901
|
||||
9 0 098901
|
||||
2 0 9 9 0 81+0+9 0 9 098001
|
||||
2 1 9 9 9 81+9+8 8 9 098001
|
||||
2 2 9 9 9 81+9+9 9 9 098001
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: mul.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
This file describes how pi is computed by the program in 'pi.c' (see
|
||||
the utils subdirectory).
|
||||
|
||||
Basically, we use Machin's formula, which is what everyone in the
|
||||
world uses as a simple method for computing approximations to pi.
|
||||
This works for up to a few thousand digits without too much effort.
|
||||
Beyond that, though, it gets too slow.
|
||||
|
||||
Machin's formula states:
|
||||
|
||||
pi := 16 * arctan(1/5) - 4 * arctan(1/239)
|
||||
|
||||
We compute this in integer arithmetic by first multiplying everything
|
||||
through by 10^d, where 'd' is the number of digits of pi we wanted to
|
||||
compute. It turns out, the last few digits will be wrong, but the
|
||||
number that are wrong is usually very small (ordinarly only 2-3).
|
||||
Having done this, we compute the arctan() function using the formula:
|
||||
|
||||
1 1 1 1 1
|
||||
arctan(1/x) := --- - ----- + ----- - ----- + ----- - ...
|
||||
x 3 x^3 5 x^5 7 x^7 9 x^9
|
||||
|
||||
This is done iteratively by computing the first term manually, and
|
||||
then iteratively dividing x^2 and k, where k = 3, 5, 7, ... out of the
|
||||
current figure. This is then added to (or subtracted from) a running
|
||||
sum, as appropriate. The iteration continues until we overflow our
|
||||
available precision and the current figure goes to zero under integer
|
||||
division. At that point, we're finished.
|
||||
|
||||
Actually, we get a couple extra bits of precision out of the fact that
|
||||
we know we're computing y * arctan(1/x), by setting up the multiplier
|
||||
as:
|
||||
|
||||
y * 10^d
|
||||
|
||||
... instead of just 10^d. There is also a bit of cleverness in how
|
||||
the loop is constructed, to avoid special-casing the first term.
|
||||
Check out the code for arctan() in 'pi.c', if you are interested in
|
||||
seeing how it is set up.
|
||||
|
||||
Thanks to Jason P. for this algorithm, which I assembled from notes
|
||||
and programs found on his cool "Pile of Pi Programs" page, at:
|
||||
|
||||
http://www.isr.umd.edu/~jasonp/pipage.html
|
||||
|
||||
Thanks also to Henrik Johansson <Henrik.Johansson@Nexus.Comm.SE>, from
|
||||
whose pi program I borrowed the clever idea of pre-multiplying by x in
|
||||
order to avoid a special case on the loop iteration.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: pi.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
prng - pseudo-random number generator
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
prng [count]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<Prng> generates 32-bit pseudo-random integers using the
|
||||
Blum-Blum-Shub (BBS) quadratic residue generator. It is seeded using
|
||||
the standard C library's rand() function, which itself seeded from the
|
||||
system clock and the process ID number. Thus, the values generated
|
||||
are not particularly useful for cryptographic applications, but they
|
||||
are in general much better than the typical output of the usual
|
||||
multiplicative congruency generator used by most runtime libraries.
|
||||
|
||||
You may optionally specify how many random values should be generated
|
||||
by giving a I<count> argument on the command line. If you do not
|
||||
specify a count, only one random value will be generated. The results
|
||||
are output to the standard output in decimal notation, one value per
|
||||
line.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
As stated above, B<prng> uses the C library's rand() function to seed
|
||||
the generator, so it is not terribly suitable for cryptographic
|
||||
applications. Also note that each time you run the program, a new
|
||||
seed is generated, so it is better to run it once with a I<count>
|
||||
parameter than it is to run it multiple times to generate several
|
||||
values.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
|
||||
Thayer School of Engineering, Dartmouth College, Hanover, NH USA
|
||||
|
||||
$Date: 2000-07-14 00:44:36 $
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
Modular Reduction
|
||||
|
||||
Usually, modular reduction is accomplished by long division, using the
|
||||
mp_div() or mp_mod() functions. However, when performing modular
|
||||
exponentiation, you spend a lot of time reducing by the same modulus
|
||||
again and again. For this purpose, doing a full division for each
|
||||
multiplication is quite inefficient.
|
||||
|
||||
For this reason, the mp_exptmod() function does not perform modular
|
||||
reductions in the usual way, but instead takes advantage of an
|
||||
algorithm due to Barrett, as described by Menezes, Oorschot and
|
||||
VanStone in their book _Handbook of Applied Cryptography_, published
|
||||
by the CRC Press (see Chapter 14 for details). This method reduces
|
||||
most of the computation of reduction to efficient shifting and masking
|
||||
operations, and avoids the multiple-precision division entirely.
|
||||
|
||||
Here is a brief synopsis of Barrett reduction, as it is implemented in
|
||||
this library.
|
||||
|
||||
Let b denote the radix of the computation (one more than the maximum
|
||||
value that can be denoted by an mp_digit). Let m be the modulus, and
|
||||
let k be the number of significant digits of m. Let x be the value to
|
||||
be reduced modulo m. By the Division Theorem, there exist unique
|
||||
integers Q and R such that:
|
||||
|
||||
x = Qm + R, 0 <= R < m
|
||||
|
||||
Barrett reduction takes advantage of the fact that you can easily
|
||||
approximate Q to within two, given a value M such that:
|
||||
|
||||
2k
|
||||
b
|
||||
M = floor( ----- )
|
||||
m
|
||||
|
||||
Computation of M requires a full-precision division step, so if you
|
||||
are only doing a single reduction by m, you gain no advantage.
|
||||
However, when multiple reductions by the same m are required, this
|
||||
division need only be done once, beforehand. Using this, we can use
|
||||
the following equation to compute Q', an approximation of Q:
|
||||
|
||||
x
|
||||
floor( ------ ) M
|
||||
k-1
|
||||
b
|
||||
Q' = floor( ----------------- )
|
||||
k+1
|
||||
b
|
||||
|
||||
The divisions by b^(k-1) and b^(k+1) and the floor() functions can be
|
||||
efficiently implemented with shifts and masks, leaving only a single
|
||||
multiplication to be performed to get this approximation. It can be
|
||||
shown that Q - 2 <= Q' <= Q, so in the worst case, we can get out with
|
||||
two additional subtractions to bring the value into line with the
|
||||
actual value of Q.
|
||||
|
||||
Once we've got Q', we basically multiply that by m and subtract from
|
||||
x, yielding:
|
||||
|
||||
x - Q'm = Qm + R - Q'm
|
||||
|
||||
Since we know the constraint on Q', this is one of:
|
||||
|
||||
R
|
||||
m + R
|
||||
2m + R
|
||||
|
||||
Since R < m by the Division Theorem, we can simply subtract off m
|
||||
until we get a value in the correct range, which will happen with no
|
||||
more than 2 subtractions:
|
||||
|
||||
v = x - Q'm
|
||||
|
||||
while(v >= m)
|
||||
v = v - m
|
||||
endwhile
|
||||
|
||||
|
||||
In random performance trials, modular exponentiation using this method
|
||||
of reduction gave around a 40% speedup over using the division for
|
||||
reduction.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: redux.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
@@ -1,87 +0,0 @@
|
||||
Square Root
|
||||
|
||||
A simple iterative algorithm is used to compute the greatest integer
|
||||
less than or equal to the square root. Essentially, this is Newton's
|
||||
linear approximation, computed by finding successive values of the
|
||||
equation:
|
||||
|
||||
x[k]^2 - V
|
||||
x[k+1] = x[k] - ------------
|
||||
2 x[k]
|
||||
|
||||
...where V is the value for which the square root is being sought. In
|
||||
essence, what is happening here is that we guess a value for the
|
||||
square root, then figure out how far off we were by squaring our guess
|
||||
and subtracting the target. Using this value, we compute a linear
|
||||
approximation for the error, and adjust the "guess". We keep doing
|
||||
this until the precision gets low enough that the above equation
|
||||
yields a quotient of zero. At this point, our last guess is one
|
||||
greater than the square root we're seeking.
|
||||
|
||||
The initial guess is computed by dividing V by 4, which is a heuristic
|
||||
I have found to be fairly good on average. This also has the
|
||||
advantage of being very easy to compute efficiently, even for large
|
||||
values.
|
||||
|
||||
So, the resulting algorithm works as follows:
|
||||
|
||||
x = V / 4 /* compute initial guess */
|
||||
|
||||
loop
|
||||
t = (x * x) - V /* Compute absolute error */
|
||||
u = 2 * x /* Adjust by tangent slope */
|
||||
t = t / u
|
||||
|
||||
/* Loop is done if error is zero */
|
||||
if(t == 0)
|
||||
break
|
||||
|
||||
/* Adjust guess by error term */
|
||||
x = x - t
|
||||
end
|
||||
|
||||
x = x - 1
|
||||
|
||||
The result of the computation is the value of x.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: sqrt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
Squaring Algorithm
|
||||
|
||||
When you are squaring a value, you can take advantage of the fact that
|
||||
half the multiplications performed by the more general multiplication
|
||||
algorithm (see 'mul.txt' for a description) are redundant when the
|
||||
multiplicand equals the multiplier.
|
||||
|
||||
In particular, the modified algorithm is:
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#a - 1)
|
||||
w = c[2*j] + (a[j] ^ 2);
|
||||
k = w div R
|
||||
|
||||
for i <- j+1 to (#a - 1)
|
||||
w = (2 * a[j] * a[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
On the surface, this looks identical to the multiplication algorithm;
|
||||
however, note the following differences:
|
||||
|
||||
- precomputation of the leading term in the outer loop
|
||||
|
||||
- i runs from j+1 instead of from zero
|
||||
|
||||
- doubling of a[i] * a[j] in the inner product
|
||||
|
||||
Unfortunately, the construction of the inner product is such that we
|
||||
need more than two digits to represent the inner product, in some
|
||||
cases. In a C implementation, this means that some gymnastics must be
|
||||
performed in order to handle overflow, for which C has no direct
|
||||
abstraction. We do this by observing the following:
|
||||
|
||||
If we have multiplied a[i] and a[j], and the product is more than half
|
||||
the maximum value expressible in two digits, then doubling this result
|
||||
will overflow into a third digit. If this occurs, we take note of the
|
||||
overflow, and double it anyway -- C integer arithmetic ignores
|
||||
overflow, so the two digits we get back should still be valid, modulo
|
||||
the overflow.
|
||||
|
||||
Having doubled this value, we now have to add in the remainders and
|
||||
the digits already computed by earlier steps. If we did not overflow
|
||||
in the previous step, we might still cause an overflow here. That
|
||||
will happen whenever the maximum value expressible in two digits, less
|
||||
the amount we have to add, is greater than the result of the previous
|
||||
step. Thus, the overflow computation is:
|
||||
|
||||
|
||||
u = 0
|
||||
w = a[i] * a[j]
|
||||
|
||||
if(w > (R - 1)/ 2)
|
||||
u = 1;
|
||||
|
||||
w = w * 2
|
||||
v = c[i + j] + k
|
||||
|
||||
if(u == 0 && (R - 1 - v) < w)
|
||||
u = 1
|
||||
|
||||
If there is an overflow, u will be 1, otherwise u will be 0. The rest
|
||||
of the parameters are the same as they are in the above description.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: square.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
MPI Library Timing Tests
|
||||
|
||||
Hardware/OS
|
||||
(A) SGI O2 1 x MIPS R10000 250MHz IRIX 6.5.3
|
||||
(B) IBM RS/6000 43P-240 1 x PowerPC 603e 223MHz AIX 4.3
|
||||
(C) Dell GX1/L+ 1 x Pentium III 550MHz Linux 2.2.12-20
|
||||
(D) PowerBook G3 1 x PowerPC 750 266MHz LinuxPPC 2.2.6-15apmac
|
||||
(E) PowerBook G3 1 x PowerPC 750 266MHz MacOS 8.5.1
|
||||
(F) PowerBook G3 1 x PowerPC 750 400MHz MacOS 9.0.2
|
||||
|
||||
Compiler
|
||||
(1) MIPSpro C 7.2.1 -O3 optimizations
|
||||
(2) GCC 2.95.1 -O3 optimizations
|
||||
(3) IBM AIX xlc -O3 optimizations (version unknown)
|
||||
(4) EGCS 2.91.66 -O3 optimizations
|
||||
(5) Metrowerks CodeWarrior 5.0 C, all optimizations
|
||||
(6) MIPSpro C 7.30 -O3 optimizations
|
||||
(7) same as (6), with optimized libmalloc.so
|
||||
|
||||
Timings are given in seconds, computed using the C library's clock()
|
||||
function. The first column gives the hardware and compiler
|
||||
configuration used for the test. The second column indicates the
|
||||
number of tests that were aggregated to get the statistics for that
|
||||
size. These were compiled using 16 bit digits.
|
||||
|
||||
Source data were generated randomly using a fixed seed, so they should
|
||||
be internally consistent, but may vary on different systems depending
|
||||
on the C library. Also, since the resolution of the timer accessed by
|
||||
clock() varies, there may be some variance in the precision of these
|
||||
measurements.
|
||||
|
||||
Prime Generation (primegen)
|
||||
|
||||
128 bits:
|
||||
A1 200 min=0.03, avg=0.19, max=0.72, sum=38.46
|
||||
A2 200 min=0.02, avg=0.16, max=0.62, sum=32.55
|
||||
B3 200 min=0.01, avg=0.07, max=0.22, sum=13.29
|
||||
C4 200 min=0.00, avg=0.03, max=0.20, sum=6.14
|
||||
D4 200 min=0.00, avg=0.05, max=0.33, sum=9.70
|
||||
A6 200 min=0.01, avg=0.09, max=0.36, sum=17.48
|
||||
A7 200 min=0.00, avg=0.05, max=0.24, sum=10.07
|
||||
|
||||
192 bits:
|
||||
A1 200 min=0.05, avg=0.45, max=3.13, sum=89.96
|
||||
A2 200 min=0.04, avg=0.39, max=2.61, sum=77.55
|
||||
B3 200 min=0.02, avg=0.18, max=1.25, sum=36.97
|
||||
C4 200 min=0.01, avg=0.09, max=0.33, sum=18.24
|
||||
D4 200 min=0.02, avg=0.15, max=0.54, sum=29.63
|
||||
A6 200 min=0.02, avg=0.24, max=1.70, sum=47.84
|
||||
A7 200 min=0.01, avg=0.15, max=1.05, sum=30.88
|
||||
|
||||
256 bits:
|
||||
A1 200 min=0.08, avg=0.92, max=6.13, sum=184.79
|
||||
A2 200 min=0.06, avg=0.76, max=5.03, sum=151.11
|
||||
B3 200 min=0.04, avg=0.41, max=2.68, sum=82.35
|
||||
C4 200 min=0.02, avg=0.19, max=0.69, sum=37.91
|
||||
D4 200 min=0.03, avg=0.31, max=1.15, sum=63.00
|
||||
A6 200 min=0.04, avg=0.48, max=3.13, sum=95.46
|
||||
A7 200 min=0.03, avg=0.37, max=2.36, sum=73.60
|
||||
|
||||
320 bits:
|
||||
A1 200 min=0.11, avg=1.59, max=6.14, sum=318.81
|
||||
A2 200 min=0.09, avg=1.27, max=4.93, sum=254.03
|
||||
B3 200 min=0.07, avg=0.82, max=3.13, sum=163.80
|
||||
C4 200 min=0.04, avg=0.44, max=1.91, sum=87.59
|
||||
D4 200 min=0.06, avg=0.73, max=3.22, sum=146.73
|
||||
A6 200 min=0.07, avg=0.93, max=3.50, sum=185.01
|
||||
A7 200 min=0.05, avg=0.76, max=2.94, sum=151.78
|
||||
|
||||
384 bits:
|
||||
A1 200 min=0.16, avg=2.69, max=11.41, sum=537.89
|
||||
A2 200 min=0.13, avg=2.15, max=9.03, sum=429.14
|
||||
B3 200 min=0.11, avg=1.54, max=6.49, sum=307.78
|
||||
C4 200 min=0.06, avg=0.81, max=4.84, sum=161.13
|
||||
D4 200 min=0.10, avg=1.38, max=8.31, sum=276.81
|
||||
A6 200 min=0.11, avg=1.73, max=7.36, sum=345.55
|
||||
A7 200 min=0.09, avg=1.46, max=6.12, sum=292.02
|
||||
|
||||
448 bits:
|
||||
A1 200 min=0.23, avg=3.36, max=15.92, sum=672.63
|
||||
A2 200 min=0.17, avg=2.61, max=12.25, sum=522.86
|
||||
B3 200 min=0.16, avg=2.10, max=9.83, sum=420.86
|
||||
C4 200 min=0.09, avg=1.44, max=7.64, sum=288.36
|
||||
D4 200 min=0.16, avg=2.50, max=13.29, sum=500.17
|
||||
A6 200 min=0.15, avg=2.31, max=10.81, sum=461.58
|
||||
A7 200 min=0.14, avg=2.03, max=9.53, sum=405.16
|
||||
|
||||
512 bits:
|
||||
A1 200 min=0.30, avg=6.12, max=22.18, sum=1223.35
|
||||
A2 200 min=0.25, avg=4.67, max=16.90, sum=933.18
|
||||
B3 200 min=0.23, avg=4.13, max=14.94, sum=825.45
|
||||
C4 200 min=0.13, avg=2.08, max=9.75, sum=415.22
|
||||
D4 200 min=0.24, avg=4.04, max=20.18, sum=808.11
|
||||
A6 200 min=0.22, avg=4.47, max=16.19, sum=893.83
|
||||
A7 200 min=0.20, avg=4.03, max=14.65, sum=806.02
|
||||
|
||||
Modular Exponentation (metime)
|
||||
|
||||
The following results are aggregated from 200 pseudo-randomly
|
||||
generated tests, based on a fixed seed.
|
||||
|
||||
base, exponent, and modulus size (bits)
|
||||
P/C 128 192 256 320 384 448 512 640 768 896 1024
|
||||
------- -----------------------------------------------------------------
|
||||
A1 0.015 0.027 0.047 0.069 0.098 0.133 0.176 0.294 0.458 0.680 1.040
|
||||
A2 0.013 0.024 0.037 0.053 0.077 0.102 0.133 0.214 0.326 0.476 0.668
|
||||
B3 0.005 0.011 0.021 0.036 0.056 0.084 0.121 0.222 0.370 0.573 0.840
|
||||
C4 0.002 0.006 0.011 0.020 0.032 0.048 0.069 0.129 0.223 0.344 0.507
|
||||
D4 0.004 0.010 0.019 0.034 0.056 0.085 0.123 0.232 0.390 0.609 0.899
|
||||
E5 0.007 0.015 0.031 0.055 0.088 0.133 0.183 0.342 0.574 0.893 1.317
|
||||
A6 0.008 0.016 0.038 0.042 0.064 0.093 0.133 0.239 0.393 0.604 0.880
|
||||
A7 0.005 0.011 0.020 0.036 0.056 0.083 0.121 0.223 0.374 0.583 0.855
|
||||
|
||||
Multiplication and Squaring tests, (mulsqr)
|
||||
|
||||
The following results are aggregated from 500000 pseudo-randomly
|
||||
generated tests, based on a per-run wall-clock seed. Times are given
|
||||
in seconds, except where indicated in microseconds (us).
|
||||
|
||||
(A1)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 9.33 9.15 > 1.9 18.7us 18.3us
|
||||
128 10.88 10.44 > 4.0 21.8us 20.9us
|
||||
192 13.30 11.89 > 10.6 26.7us 23.8us
|
||||
256 14.88 12.64 > 15.1 29.8us 25.3us
|
||||
320 18.64 15.01 > 19.5 37.3us 30.0us
|
||||
384 23.11 17.70 > 23.4 46.2us 35.4us
|
||||
448 28.28 20.88 > 26.2 56.6us 41.8us
|
||||
512 34.09 24.51 > 28.1 68.2us 49.0us
|
||||
640 47.86 33.25 > 30.5 95.7us 66.5us
|
||||
768 64.91 43.54 > 32.9 129.8us 87.1us
|
||||
896 84.49 55.48 > 34.3 169.0us 111.0us
|
||||
1024 107.25 69.21 > 35.5 214.5us 138.4us
|
||||
1536 227.97 141.91 > 37.8 456.0us 283.8us
|
||||
2048 394.05 242.15 > 38.5 788.1us 484.3us
|
||||
|
||||
(A2)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 7.87 7.95 < 1.0 15.7us 15.9us
|
||||
128 9.40 9.19 > 2.2 18.8us 18.4us
|
||||
192 11.15 10.59 > 5.0 22.3us 21.2us
|
||||
256 12.02 11.16 > 7.2 24.0us 22.3us
|
||||
320 14.62 13.43 > 8.1 29.2us 26.9us
|
||||
384 17.72 15.80 > 10.8 35.4us 31.6us
|
||||
448 21.24 18.51 > 12.9 42.5us 37.0us
|
||||
512 25.36 21.78 > 14.1 50.7us 43.6us
|
||||
640 34.57 29.00 > 16.1 69.1us 58.0us
|
||||
768 46.10 37.60 > 18.4 92.2us 75.2us
|
||||
896 58.94 47.72 > 19.0 117.9us 95.4us
|
||||
1024 73.76 59.12 > 19.8 147.5us 118.2us
|
||||
1536 152.00 118.80 > 21.8 304.0us 237.6us
|
||||
2048 259.41 199.57 > 23.1 518.8us 399.1us
|
||||
|
||||
(B3)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 2.60 2.47 > 5.0 5.20us 4.94us
|
||||
128 4.43 4.06 > 8.4 8.86us 8.12us
|
||||
192 7.03 6.10 > 13.2 14.1us 12.2us
|
||||
256 10.44 8.59 > 17.7 20.9us 17.2us
|
||||
320 14.44 11.64 > 19.4 28.9us 23.3us
|
||||
384 19.12 15.08 > 21.1 38.2us 30.2us
|
||||
448 24.55 19.09 > 22.2 49.1us 38.2us
|
||||
512 31.03 23.53 > 24.2 62.1us 47.1us
|
||||
640 45.05 33.80 > 25.0 90.1us 67.6us
|
||||
768 63.02 46.05 > 26.9 126.0us 92.1us
|
||||
896 83.74 60.29 > 28.0 167.5us 120.6us
|
||||
1024 106.73 76.65 > 28.2 213.5us 153.3us
|
||||
1536 228.94 160.98 > 29.7 457.9us 322.0us
|
||||
2048 398.08 275.93 > 30.7 796.2us 551.9us
|
||||
|
||||
(C4)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.34 1.28 > 4.5 2.68us 2.56us
|
||||
128 2.76 2.59 > 6.2 5.52us 5.18us
|
||||
192 4.52 4.16 > 8.0 9.04us 8.32us
|
||||
256 6.64 5.99 > 9.8 13.3us 12.0us
|
||||
320 9.20 8.13 > 11.6 18.4us 16.3us
|
||||
384 12.01 10.58 > 11.9 24.0us 21.2us
|
||||
448 15.24 13.33 > 12.5 30.5us 26.7us
|
||||
512 19.02 16.46 > 13.5 38.0us 32.9us
|
||||
640 27.56 23.54 > 14.6 55.1us 47.1us
|
||||
768 37.89 31.78 > 16.1 75.8us 63.6us
|
||||
896 49.24 41.42 > 15.9 98.5us 82.8us
|
||||
1024 62.59 52.18 > 16.6 125.2us 104.3us
|
||||
1536 131.66 107.72 > 18.2 263.3us 215.4us
|
||||
2048 226.45 182.95 > 19.2 453.0us 365.9us
|
||||
|
||||
(A7)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.74 1.71 > 1.7 3.48us 3.42us
|
||||
128 3.48 2.96 > 14.9 6.96us 5.92us
|
||||
192 5.74 4.60 > 19.9 11.5us 9.20us
|
||||
256 8.75 6.61 > 24.5 17.5us 13.2us
|
||||
320 12.5 8.99 > 28.1 25.0us 18.0us
|
||||
384 16.9 11.9 > 29.6 33.8us 23.8us
|
||||
448 22.2 15.2 > 31.7 44.4us 30.4us
|
||||
512 28.3 19.0 > 32.7 56.6us 38.0us
|
||||
640 42.4 28.0 > 34.0 84.8us 56.0us
|
||||
768 59.4 38.5 > 35.2 118.8us 77.0us
|
||||
896 79.5 51.2 > 35.6 159.0us 102.4us
|
||||
1024 102.6 65.5 > 36.2 205.2us 131.0us
|
||||
1536 224.3 140.6 > 37.3 448.6us 281.2us
|
||||
2048 393.4 244.3 > 37.9 786.8us 488.6us
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
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 *****
|
||||
|
||||
$Id: timing.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,640 +0,0 @@
|
||||
/*
|
||||
* 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 multacc512 multiple-precision integer arithmetic.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Hewlett-Packard Company.
|
||||
* Portions created by Hewlett-Packard Company are
|
||||
* Copyright (C) March 1999, Hewlett-Packard Company. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* coded by: Bill Worley, Hewlett-Packard labs
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*
|
||||
* This PA-RISC 2.0 function computes the product of two unsigned integers,
|
||||
* and adds the result to a previously computed integer. The multiplicand
|
||||
* is a 512-bit (64-byte, eight doubleword) unsigned integer, stored in
|
||||
* memory in little-double-wordian order. The multiplier is an unsigned
|
||||
* 64-bit integer. The previously computed integer to which the product is
|
||||
* added is located in the result ("res") area, and is assumed to be a
|
||||
* 576-bit (72-byte, nine doubleword) unsigned integer, stored in memory
|
||||
* in little-double-wordian order. This value normally will be the result
|
||||
* of a previously computed nine doubleword result. It is not necessary
|
||||
* to pad the multiplicand with an additional 64-bit zero doubleword.
|
||||
*
|
||||
* Multiplicand, multiplier, and addend ideally should be aligned at
|
||||
* 16-byte boundaries for best performance. The code will function
|
||||
* correctly for alignment at eight-byte boundaries which are not 16-byte
|
||||
* boundaries, but the execution may be slightly slower due to even/odd
|
||||
* bank conflicts on PA-RISC 8000 processors.
|
||||
*
|
||||
* This function is designed to accept the same calling sequence as Bill
|
||||
* Ackerman's "maxpy_little" function. The carry from the ninth doubleword
|
||||
* of the result is written to the tenth word of the result, as is done by
|
||||
* Bill Ackerman's function. The final carry also is returned as an
|
||||
* integer, which may be ignored. The function prototype may be either
|
||||
* of the following:
|
||||
*
|
||||
* void multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
* or
|
||||
* int multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
*
|
||||
* where: "l" originally denoted vector lengths. This parameter is
|
||||
* ignored. This function always assumes a multiplicand length of
|
||||
* 512 bits (eight doublewords), and addend and result lengths of
|
||||
* 576 bits (nine doublewords).
|
||||
*
|
||||
* "m" is a pointer to the doubleword multiplier, ideally aligned
|
||||
* on a 16-byte boundary.
|
||||
*
|
||||
* "a" is a pointer to the eight-doubleword multiplicand, stored
|
||||
* in little-double-wordian order, and ideally aligned on a 16-byte
|
||||
* boundary.
|
||||
*
|
||||
* "res" is a pointer to the nine doubleword addend, and to the
|
||||
* nine-doubleword product computed by this function. The result
|
||||
* also is stored in little-double-wordian order, and ideally is
|
||||
* aligned on a 16-byte boundary. It is expected that the alignment
|
||||
* of the "res" area may alternate between even/odd doubleword
|
||||
* boundaries for successive calls for 512-bit x 512-bit
|
||||
* multiplications.
|
||||
*
|
||||
* The code for this function has been scheduled to use the parallelism
|
||||
* of the PA-RISC 8000 series microprocessors as well as the author was
|
||||
* able. Comments and/or suggestions for improvement are welcomed.
|
||||
*
|
||||
* The code is "64-bit safe". This means it may be called in either
|
||||
* the 32ILP context or the 64LP context. All 64-bits of registers are
|
||||
* saved and restored.
|
||||
*
|
||||
* This code is self-contained. It requires no other header files in order
|
||||
* to compile and to be linkable on a PA-RISC 2.0 machine. Symbolic
|
||||
* definitions for registers and stack offsets are included within this
|
||||
* one source file.
|
||||
*
|
||||
* This is a leaf routine. As such, minimal use is made of the stack area.
|
||||
* Of the 192 bytes allocated, 64 bytes are used for saving/restoring eight
|
||||
* general registers, and 128 bytes are used to move intermediate products
|
||||
* from the floating-point registers to the general registers. Stack
|
||||
* protocols assure proper alignment of these areas.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* ====================================================================*/
|
||||
/* symbolic definitions for PA-RISC registers */
|
||||
/* in the MIPS style, avoids lots of case shifts */
|
||||
/* assigments (except t4) preserve register number parity */
|
||||
/* ====================================================================*/
|
||||
|
||||
#define zero %r0 /* permanent zero */
|
||||
#define t5 %r1 /* temp register, altered by addil */
|
||||
|
||||
#define rp %r2 /* return pointer */
|
||||
|
||||
#define s1 %r3 /* callee saves register*/
|
||||
#define s0 %r4 /* callee saves register*/
|
||||
#define s3 %r5 /* callee saves register*/
|
||||
#define s2 %r6 /* callee saves register*/
|
||||
#define s5 %r7 /* callee saves register*/
|
||||
#define s4 %r8 /* callee saves register*/
|
||||
#define s7 %r9 /* callee saves register*/
|
||||
#define s6 %r10 /* callee saves register*/
|
||||
|
||||
#define t1 %r19 /* caller saves register*/
|
||||
#define t0 %r20 /* caller saves register*/
|
||||
#define t3 %r21 /* caller saves register*/
|
||||
#define t2 %r22 /* caller saves register*/
|
||||
|
||||
#define a3 %r23 /* fourth argument register, high word */
|
||||
#define a2 %r24 /* third argument register, low word*/
|
||||
#define a1 %r25 /* second argument register, high word*/
|
||||
#define a0 %r26 /* first argument register, low word*/
|
||||
|
||||
#define v0 %r28 /* high order return value*/
|
||||
#define v1 %r29 /* low order return value*/
|
||||
|
||||
#define sp %r30 /* stack pointer*/
|
||||
#define t4 %r31 /* temporary register */
|
||||
|
||||
#define fa0 %fr4 /* first argument register*/
|
||||
#define fa1 %fr5 /* second argument register*/
|
||||
#define fa2 %fr6 /* third argument register*/
|
||||
#define fa3 %fr7 /* fourth argument register*/
|
||||
|
||||
#define fa0r %fr4R /* first argument register*/
|
||||
#define fa1r %fr5R /* second argument register*/
|
||||
#define fa2r %fr6R /* third argument register*/
|
||||
#define fa3r %fr7R /* fourth argument register*/
|
||||
|
||||
#define ft0 %fr8 /* caller saves register*/
|
||||
#define ft1 %fr9 /* caller saves register*/
|
||||
#define ft2 %fr10 /* caller saves register*/
|
||||
#define ft3 %fr11 /* caller saves register*/
|
||||
|
||||
#define ft0r %fr8R /* caller saves register*/
|
||||
#define ft1r %fr9R /* caller saves register*/
|
||||
#define ft2r %fr10R /* caller saves register*/
|
||||
#define ft3r %fr11R /* caller saves register*/
|
||||
|
||||
#define ft4 %fr22 /* caller saves register*/
|
||||
#define ft5 %fr23 /* caller saves register*/
|
||||
#define ft6 %fr24 /* caller saves register*/
|
||||
#define ft7 %fr25 /* caller saves register*/
|
||||
#define ft8 %fr26 /* caller saves register*/
|
||||
#define ft9 %fr27 /* caller saves register*/
|
||||
#define ft10 %fr28 /* caller saves register*/
|
||||
#define ft11 %fr29 /* caller saves register*/
|
||||
#define ft12 %fr30 /* caller saves register*/
|
||||
#define ft13 %fr31 /* caller saves register*/
|
||||
|
||||
#define ft4r %fr22R /* caller saves register*/
|
||||
#define ft5r %fr23R /* caller saves register*/
|
||||
#define ft6r %fr24R /* caller saves register*/
|
||||
#define ft7r %fr25R /* caller saves register*/
|
||||
#define ft8r %fr26R /* caller saves register*/
|
||||
#define ft9r %fr27R /* caller saves register*/
|
||||
#define ft10r %fr28R /* caller saves register*/
|
||||
#define ft11r %fr29R /* caller saves register*/
|
||||
#define ft12r %fr30R /* caller saves register*/
|
||||
#define ft13r %fr31R /* caller saves register*/
|
||||
|
||||
|
||||
|
||||
/* ================================================================== */
|
||||
/* functional definitions for PA-RISC registers */
|
||||
/* ================================================================== */
|
||||
|
||||
/* general registers */
|
||||
|
||||
#define T1 a0 /* temp, (length parameter ignored) */
|
||||
|
||||
#define pM a1 /* -> 64-bit multiplier */
|
||||
#define T2 a1 /* temp, (after fetching multiplier) */
|
||||
|
||||
#define pA a2 /* -> multiplicand vector (8 64-bit words) */
|
||||
#define T3 a2 /* temp, (after fetching multiplicand) */
|
||||
|
||||
#define pR a3 /* -> addend vector (8 64-bit doublewords,
|
||||
result vector (9 64-bit words) */
|
||||
|
||||
#define S0 s0 /* callee saves summand registers */
|
||||
#define S1 s1
|
||||
#define S2 s2
|
||||
#define S3 s3
|
||||
#define S4 s4
|
||||
#define S5 s5
|
||||
#define S6 s6
|
||||
#define S7 s7
|
||||
|
||||
#define S8 v0 /* caller saves summand registers */
|
||||
#define S9 v1
|
||||
#define S10 t0
|
||||
#define S11 t1
|
||||
#define S12 t2
|
||||
#define S13 t3
|
||||
#define S14 t4
|
||||
#define S15 t5
|
||||
|
||||
|
||||
|
||||
/* floating-point registers */
|
||||
|
||||
#define M fa0 /* multiplier double word */
|
||||
#define MR fa0r /* low order half of multiplier double word */
|
||||
#define ML fa0 /* high order half of multiplier double word */
|
||||
|
||||
#define A0 fa2 /* multiplicand double word 0 */
|
||||
#define A0R fa2r /* low order half of multiplicand double word */
|
||||
#define A0L fa2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A1 fa3 /* multiplicand double word 1 */
|
||||
#define A1R fa3r /* low order half of multiplicand double word */
|
||||
#define A1L fa3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A2 ft0 /* multiplicand double word 2 */
|
||||
#define A2R ft0r /* low order half of multiplicand double word */
|
||||
#define A2L ft0 /* high order half of multiplicand double word */
|
||||
|
||||
#define A3 ft1 /* multiplicand double word 3 */
|
||||
#define A3R ft1r /* low order half of multiplicand double word */
|
||||
#define A3L ft1 /* high order half of multiplicand double word */
|
||||
|
||||
#define A4 ft2 /* multiplicand double word 4 */
|
||||
#define A4R ft2r /* low order half of multiplicand double word */
|
||||
#define A4L ft2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A5 ft3 /* multiplicand double word 5 */
|
||||
#define A5R ft3r /* low order half of multiplicand double word */
|
||||
#define A5L ft3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A6 ft4 /* multiplicand double word 6 */
|
||||
#define A6R ft4r /* low order half of multiplicand double word */
|
||||
#define A6L ft4 /* high order half of multiplicand double word */
|
||||
|
||||
#define A7 ft5 /* multiplicand double word 7 */
|
||||
#define A7R ft5r /* low order half of multiplicand double word */
|
||||
#define A7L ft5 /* high order half of multiplicand double word */
|
||||
|
||||
#define P0 ft6 /* product word 0 */
|
||||
#define P1 ft7 /* product word 0 */
|
||||
#define P2 ft8 /* product word 0 */
|
||||
#define P3 ft9 /* product word 0 */
|
||||
#define P4 ft10 /* product word 0 */
|
||||
#define P5 ft11 /* product word 0 */
|
||||
#define P6 ft12 /* product word 0 */
|
||||
#define P7 ft13 /* product word 0 */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* symbolic definitions for HP-UX stack offsets */
|
||||
/* symbolic definitions for memory NOPs */
|
||||
/* ====================================================================== */
|
||||
|
||||
#define ST_SZ 192 /* stack area total size */
|
||||
|
||||
#define SV0 -192(sp) /* general register save area */
|
||||
#define SV1 -184(sp)
|
||||
#define SV2 -176(sp)
|
||||
#define SV3 -168(sp)
|
||||
#define SV4 -160(sp)
|
||||
#define SV5 -152(sp)
|
||||
#define SV6 -144(sp)
|
||||
#define SV7 -136(sp)
|
||||
|
||||
#define XF0 -128(sp) /* data transfer area */
|
||||
#define XF1 -120(sp) /* for floating-pt to integer regs */
|
||||
#define XF2 -112(sp)
|
||||
#define XF3 -104(sp)
|
||||
#define XF4 -96(sp)
|
||||
#define XF5 -88(sp)
|
||||
#define XF6 -80(sp)
|
||||
#define XF7 -72(sp)
|
||||
#define XF8 -64(sp)
|
||||
#define XF9 -56(sp)
|
||||
#define XF10 -48(sp)
|
||||
#define XF11 -40(sp)
|
||||
#define XF12 -32(sp)
|
||||
#define XF13 -24(sp)
|
||||
#define XF14 -16(sp)
|
||||
#define XF15 -8(sp)
|
||||
|
||||
#define mnop proberi (sp),3,zero /* memory NOP */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* assembler formalities */
|
||||
/* ====================================================================== */
|
||||
|
||||
#ifdef __LP64__
|
||||
.level 2.0W
|
||||
#else
|
||||
.level 2.0
|
||||
#endif
|
||||
.space $TEXT$
|
||||
.subspa $CODE$
|
||||
.align 16
|
||||
|
||||
/* ====================================================================== */
|
||||
/* here to compute 64-bit x 512-bit product + 512-bit addend */
|
||||
/* ====================================================================== */
|
||||
|
||||
multacc512
|
||||
.PROC
|
||||
.CALLINFO
|
||||
.ENTER
|
||||
fldd 0(pM),M ; multiplier double word
|
||||
ldo ST_SZ(sp),sp ; push stack
|
||||
|
||||
fldd 0(pA),A0 ; multiplicand double word 0
|
||||
std S1,SV1 ; save s1
|
||||
|
||||
fldd 16(pA),A2 ; multiplicand double word 2
|
||||
std S3,SV3 ; save s3
|
||||
|
||||
fldd 32(pA),A4 ; multiplicand double word 4
|
||||
std S5,SV5 ; save s5
|
||||
|
||||
fldd 48(pA),A6 ; multiplicand double word 6
|
||||
std S7,SV7 ; save s7
|
||||
|
||||
|
||||
std S0,SV0 ; save s0
|
||||
fldd 8(pA),A1 ; multiplicand double word 1
|
||||
xmpyu MR,A0L,P0 ; A0 cross 32-bit word products
|
||||
xmpyu ML,A0R,P2
|
||||
|
||||
std S2,SV2 ; save s2
|
||||
fldd 24(pA),A3 ; multiplicand double word 3
|
||||
xmpyu MR,A2L,P4 ; A2 cross 32-bit word products
|
||||
xmpyu ML,A2R,P6
|
||||
|
||||
std S4,SV4 ; save s4
|
||||
fldd 40(pA),A5 ; multiplicand double word 5
|
||||
|
||||
std S6,SV6 ; save s6
|
||||
fldd 56(pA),A7 ; multiplicand double word 7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0L
|
||||
xmpyu MR,A0R,P0 ; A0 right 32-bit word product
|
||||
xmpyu MR,A1L,P1 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P2,XF2 ; ML * A0R
|
||||
xmpyu ML,A0L,P2 ; A0 left 32-bit word product
|
||||
xmpyu ML,A1R,P3 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P4,XF4 ; MR * A2L
|
||||
xmpyu MR,A2R,P4 ; A2 right 32-bit word product
|
||||
xmpyu MR,A3L,P5 ; A3 cross 32-bit word product
|
||||
|
||||
fstd P6,XF6 ; ML * A2R
|
||||
xmpyu ML,A2L,P6 ; A2 parallel 32-bit word product
|
||||
xmpyu ML,A3R,P7 ; A3 cross 32-bit word product
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A0L
|
||||
fstd P1,XF1 ; MR * A1L
|
||||
|
||||
ldd XF2,S2 ; ML * A0R
|
||||
fstd P3,XF3 ; ML * A1R
|
||||
|
||||
ldd XF4,S4 ; MR * A2L
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A1R,P1 ; A1 parallel 32-bit word products
|
||||
xmpyu ML,A1L,P3
|
||||
|
||||
ldd XF6,S6 ; ML * A2R
|
||||
fstd P7,XF7 ; ML * A3R
|
||||
xmpyu MR,A3R,P5 ; A3 parallel 32-bit word products
|
||||
xmpyu ML,A3L,P7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0R
|
||||
ldd XF1,S1 ; MR * A1L
|
||||
nop
|
||||
add S0,S2,T1 ; A0 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A0L
|
||||
ldd XF3,S3 ; ML * A1R
|
||||
add,dc zero,zero,S0 ; A0 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A0 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A2R
|
||||
ldd XF5,S5 ; MR * A3L
|
||||
shrpd S0,T1,32,S0 ; A0 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A2 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A2L
|
||||
ldd XF7,S7 ; ML * A3R
|
||||
add,dc zero,zero,S4 ; A2 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A2 cross product sum << 32
|
||||
|
||||
|
||||
ldd XF0,S8 ; MR * A0R
|
||||
fstd P1,XF1 ; MR * A1R
|
||||
xmpyu MR,A4L,P0 ; A4 cross 32-bit word product
|
||||
xmpyu MR,A5L,P1 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF2,S10 ; ML * A0L
|
||||
fstd P3,XF3 ; ML * A1L
|
||||
xmpyu ML,A4R,P2 ; A4 cross 32-bit word product
|
||||
xmpyu ML,A5R,P3 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF4,S12 ; MR * A2R
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A6L,P4 ; A6 cross 32-bit word product
|
||||
xmpyu MR,A7L,P5 ; A7 cross 32-bit word product
|
||||
|
||||
ldd XF6,S14 ; ML * A2L
|
||||
fstd P7,XF7 ; ML * A3L
|
||||
xmpyu ML,A6R,P6 ; A6 cross 32-bit word product
|
||||
xmpyu ML,A7R,P7 ; A7 cross 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4L
|
||||
ldd XF1,S9 ; MR * A1R
|
||||
shrpd S4,T3,32,S4 ; A2 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A1 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A4R
|
||||
ldd XF3,S11 ; ML * A1L
|
||||
add,dc zero,zero,S1 ; A1 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A1 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A6L
|
||||
ldd XF5,S13 ; MR * A3R
|
||||
shrpd S1,T1,32,S1 ; A1 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A3 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A6R
|
||||
ldd XF7,S15 ; ML * A3L
|
||||
add,dc zero,zero,S5 ; A3 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A3 cross product sum << 32
|
||||
|
||||
|
||||
shrpd S5,T3,32,S5 ; A3 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A0 right doubleword, P0 doubleword
|
||||
|
||||
add,dc S0,S10,S10 ; M * A0 left doubleword
|
||||
add S3,S9,S9 ; M * A1 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A1 left doubleword
|
||||
add S6,S12,S12 ; M * A2 right doubleword
|
||||
|
||||
|
||||
ldd 24(pR),S3 ; Addend word 3
|
||||
fstd P1,XF1 ; MR * A5L
|
||||
add,dc S4,S14,S14 ; M * A2 left doubleword
|
||||
xmpyu MR,A5R,P1 ; A5 right 32-bit word product
|
||||
|
||||
ldd 8(pR),S1 ; Addend word 1
|
||||
fstd P3,XF3 ; ML * A5R
|
||||
add S7,S13,S13 ; M * A3 right doubleword
|
||||
xmpyu ML,A5L,P3 ; A5 left 32-bit word product
|
||||
|
||||
ldd 0(pR),S7 ; Addend word 0
|
||||
fstd P5,XF5 ; MR * A7L
|
||||
add,dc S5,S15,S15 ; M * A3 left doubleword
|
||||
xmpyu MR,A7R,P5 ; A7 right 32-bit word product
|
||||
|
||||
ldd 16(pR),S5 ; Addend word 2
|
||||
fstd P7,XF7 ; ML * A7R
|
||||
add S10,S9,S9 ; P1 doubleword
|
||||
xmpyu ML,A7L,P7 ; A7 left 32-bit word products
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A4L
|
||||
fstd P1,XF9 ; MR * A5R
|
||||
add,dc S11,S12,S12 ; P2 doubleword
|
||||
xmpyu MR,A4R,P0 ; A4 right 32-bit word product
|
||||
|
||||
ldd XF2,S2 ; ML * A4R
|
||||
fstd P3,XF11 ; ML * A5L
|
||||
add,dc S14,S13,S13 ; P3 doubleword
|
||||
xmpyu ML,A4L,P2 ; A4 left 32-bit word product
|
||||
|
||||
ldd XF6,S6 ; ML * A6R
|
||||
fstd P5,XF13 ; MR * A7R
|
||||
add,dc zero,S15,T2 ; P4 partial doubleword
|
||||
xmpyu MR,A6R,P4 ; A6 right 32-bit word product
|
||||
|
||||
ldd XF4,S4 ; MR * A6L
|
||||
fstd P7,XF15 ; ML * A7L
|
||||
add S7,S8,S8 ; R0 + P0, new R0 doubleword
|
||||
xmpyu ML,A6L,P6 ; A6 left 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4R
|
||||
ldd XF7,S7 ; ML * A7R
|
||||
add,dc S1,S9,S9 ; c + R1 + P1, new R1 doubleword
|
||||
|
||||
fstd P2,XF2 ; ML * A4L
|
||||
ldd XF1,S1 ; MR * A5L
|
||||
add,dc S5,S12,S12 ; c + R2 + P2, new R2 doubleword
|
||||
|
||||
fstd P4,XF4 ; MR * A6R
|
||||
ldd XF5,S5 ; MR * A7L
|
||||
add,dc S3,S13,S13 ; c + R3 + P3, new R3 doubleword
|
||||
|
||||
fstd P6,XF6 ; ML * A6L
|
||||
ldd XF3,S3 ; ML * A5R
|
||||
add,dc zero,T2,T2 ; c + partial P4
|
||||
add S0,S2,T1 ; A4 cross product sum
|
||||
|
||||
|
||||
std S8,0(pR) ; save R0
|
||||
add,dc zero,zero,S0 ; A4 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A4 cross product sum << 32
|
||||
|
||||
std S9,8(pR) ; save R1
|
||||
shrpd S0,T1,32,S0 ; A4 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A6 cross product sum
|
||||
|
||||
std S12,16(pR) ; save R2
|
||||
add,dc zero,zero,S4 ; A6 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A6 cross product sum << 32
|
||||
|
||||
|
||||
std S13,24(pR) ; save R3
|
||||
shrpd S4,T3,32,S4 ; A6 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A5 cross product sum
|
||||
|
||||
ldd XF0,S8 ; MR * A4R
|
||||
add,dc zero,zero,S1 ; A5 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A5 cross product sum << 32
|
||||
|
||||
ldd XF2,S10 ; ML * A4L
|
||||
ldd XF9,S9 ; MR * A5R
|
||||
shrpd S1,T1,32,S1 ; A5 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A7 cross product sum
|
||||
|
||||
ldd XF4,S12 ; MR * A6R
|
||||
ldd XF11,S11 ; ML * A5L
|
||||
add,dc zero,zero,S5 ; A7 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A7 cross product sum << 32
|
||||
|
||||
ldd XF6,S14 ; ML * A6L
|
||||
ldd XF13,S13 ; MR * A7R
|
||||
shrpd S5,T3,32,S5 ; A7 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A4 right doubleword
|
||||
|
||||
|
||||
ldd XF15,S15 ; ML * A7L
|
||||
add,dc S0,S10,S10 ; M * A4 left doubleword
|
||||
add S3,S9,S9 ; M * A5 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A5 left doubleword
|
||||
add S6,S12,S12 ; M * A6 right doubleword
|
||||
|
||||
ldd 32(pR),S0 ; Addend word 4
|
||||
ldd 40(pR),S1 ; Addend word 5
|
||||
add,dc S4,S14,S14 ; M * A6 left doubleword
|
||||
add S7,S13,S13 ; M * A7 right doubleword
|
||||
|
||||
ldd 48(pR),S2 ; Addend word 6
|
||||
ldd 56(pR),S3 ; Addend word 7
|
||||
add,dc S5,S15,S15 ; M * A7 left doubleword
|
||||
add S8,T2,S8 ; P4 doubleword
|
||||
|
||||
ldd 64(pR),S4 ; Addend word 8
|
||||
ldd SV5,s5 ; restore s5
|
||||
add,dc S10,S9,S9 ; P5 doubleword
|
||||
add,dc S11,S12,S12 ; P6 doubleword
|
||||
|
||||
|
||||
ldd SV6,s6 ; restore s6
|
||||
ldd SV7,s7 ; restore s7
|
||||
add,dc S14,S13,S13 ; P7 doubleword
|
||||
add,dc zero,S15,S15 ; P8 doubleword
|
||||
|
||||
add S0,S8,S8 ; new R4 doubleword
|
||||
|
||||
ldd SV0,s0 ; restore s0
|
||||
std S8,32(pR) ; save R4
|
||||
add,dc S1,S9,S9 ; new R5 doubleword
|
||||
|
||||
ldd SV1,s1 ; restore s1
|
||||
std S9,40(pR) ; save R5
|
||||
add,dc S2,S12,S12 ; new R6 doubleword
|
||||
|
||||
ldd SV2,s2 ; restore s2
|
||||
std S12,48(pR) ; save R6
|
||||
add,dc S3,S13,S13 ; new R7 doubleword
|
||||
|
||||
ldd SV3,s3 ; restore s3
|
||||
std S13,56(pR) ; save R7
|
||||
add,dc S4,S15,S15 ; new R8 doubleword
|
||||
|
||||
ldd SV4,s4 ; restore s4
|
||||
std S15,64(pR) ; save result[8]
|
||||
add,dc zero,zero,v0 ; return carry from R8
|
||||
|
||||
CMPIB,*= 0,v0,$L0 ; if no overflow, exit
|
||||
LDO 8(pR),pR
|
||||
|
||||
$FINAL1 ; Final carry propagation
|
||||
LDD 64(pR),v0
|
||||
LDO 8(pR),pR
|
||||
ADDI 1,v0,v0
|
||||
CMPIB,*= 0,v0,$FINAL1 ; Keep looping if there is a carry.
|
||||
STD v0,56(pR)
|
||||
$L0
|
||||
bv zero(rp) ; -> caller
|
||||
ldo -ST_SZ(sp),sp ; pop stack
|
||||
|
||||
/* ====================================================================== */
|
||||
/* end of module */
|
||||
/* ====================================================================== */
|
||||
|
||||
.LEAVE
|
||||
|
||||
.PROCEND
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.EXPORT multacc512,ENTRY
|
||||
|
||||
.end
|
||||
@@ -1,929 +0,0 @@
|
||||
; 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 MAXPY multiple-precision integer arithmetic.
|
||||
;
|
||||
; The Initial Developer of the Original Code is the Hewlett-Packard Company.
|
||||
; Portions created by Hewlett-Packard Company are
|
||||
; Copyright (C) 1997 Hewlett-Packard Company. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
; coded by: William B. Ackerman
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the
|
||||
; terms of the GNU General Public License Version 2 or later (the
|
||||
; "GPL"), in which case the provisions of the GPL are applicable
|
||||
; instead of those above. If you wish to allow use of your
|
||||
; version of this file only under the terms of the GPL and not to
|
||||
; allow others to use your version of this file under the MPL,
|
||||
; indicate your decision by deleting the provisions above and
|
||||
; replace them with the notice and other provisions required by
|
||||
; the GPL. If you do not delete the provisions above, a recipient
|
||||
; may use your version of this file under either the MPL or the
|
||||
; GPL.
|
||||
|
||||
#ifdef __LP64__
|
||||
.LEVEL 2.0W
|
||||
#else
|
||||
; .LEVEL 1.1
|
||||
; .ALLOW 2.0N
|
||||
.LEVEL 2.0N
|
||||
#endif
|
||||
.SPACE $TEXT$,SORT=8
|
||||
.SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
|
||||
|
||||
; ***************************************************************
|
||||
;
|
||||
; maxpy_[little/big]
|
||||
;
|
||||
; ***************************************************************
|
||||
|
||||
; There is no default -- you must specify one or the other.
|
||||
#define LITTLE_WORDIAN 1
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
#define EIGHT 8
|
||||
#define SIXTEEN 16
|
||||
#define THIRTY_TWO 32
|
||||
#define UN_EIGHT -8
|
||||
#define UN_SIXTEEN -16
|
||||
#define UN_TWENTY_FOUR -24
|
||||
#endif
|
||||
|
||||
#ifdef BIG_WORDIAN
|
||||
#define EIGHT -8
|
||||
#define SIXTEEN -16
|
||||
#define THIRTY_TWO -32
|
||||
#define UN_EIGHT 8
|
||||
#define UN_SIXTEEN 16
|
||||
#define UN_TWENTY_FOUR 24
|
||||
#endif
|
||||
|
||||
; This performs a multiple-precision integer version of "daxpy",
|
||||
; Using the selected addressing direction. "Little-wordian" means that
|
||||
; the least significant word of a number is stored at the lowest address.
|
||||
; "Big-wordian" means that the most significant word is at the lowest
|
||||
; address. Either way, the incoming address of the vector is that
|
||||
; of the least significant word. That means that, for little-wordian
|
||||
; addressing, we move the address upward as we propagate carries
|
||||
; from the least significant word to the most significant. For
|
||||
; big-wordian we move the address downward.
|
||||
|
||||
; We use the following registers:
|
||||
;
|
||||
; r2 return PC, of course
|
||||
; r26 = arg1 = length
|
||||
; r25 = arg2 = address of scalar
|
||||
; r24 = arg3 = multiplicand vector
|
||||
; r23 = arg4 = result vector
|
||||
;
|
||||
; fr9 = scalar loaded once only from r25
|
||||
|
||||
; The cycle counts shown in the bodies below are simply the result of a
|
||||
; scheduling by hand. The actual PCX-U hardware does it differently.
|
||||
; The intention is that the overall speed is the same.
|
||||
|
||||
; The pipeline startup and shutdown code is constructed in the usual way,
|
||||
; by taking the loop bodies and removing unnecessary instructions.
|
||||
; We have left the comments describing cycle numbers in the code.
|
||||
; These are intended for reference when comparing with the main loop,
|
||||
; and have no particular relationship to actual cycle numbers.
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
maxpy_little
|
||||
#else
|
||||
maxpy_big
|
||||
#endif
|
||||
.PROC
|
||||
.CALLINFO FRAME=120,ENTRY_GR=%r4
|
||||
.ENTER
|
||||
|
||||
; Of course, real men don't use the sissy "enter" and "leave" commands.
|
||||
; They write their own stack manipulation stuff. Unfortunately,
|
||||
; that doesn't generate complete unwind info, whereas "enter" and
|
||||
; "leave" (if the documentation is to be believed) do so. Therefore,
|
||||
; we use the sissy commands. We have verified (by real-man methods)
|
||||
; that the above command generates what we want:
|
||||
; STW,MA %r3,128(%sp)
|
||||
; STW %r4,-124(%sp)
|
||||
|
||||
ADDIB,< -1,%r26,$L0 ; If N = 0, exit immediately.
|
||||
FLDD 0(%r25),%fr9 ; fr9 = scalar
|
||||
|
||||
; First startup
|
||||
|
||||
FLDD 0(%r24),%fr24 ; Cycle 1
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
CMPIB,> 3,%r26,$N_IS_SMALL ; Pick out cases N = 1, 2, or 3
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
FSTD %fr24,-96(%sp)
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
FSTD %fr25,-80(%sp)
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
; Second startup
|
||||
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
FSTD %fr30,-56(%sp)
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
LDD -56(%sp),%r20
|
||||
ADD %r21,%r3,%r3
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
LDD -104(%sp),%r31
|
||||
ADD,DC %r0,%r0,%r20
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
|
||||
LDD -72(%sp),%r29 ; Cycle 9
|
||||
SHRPD %r20,%r19,32,%r20
|
||||
ADD %r21,%r1,%r1
|
||||
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
ADD,DC %r3,%r4,%r4
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
ADD,DC %r0,%r20,%r20
|
||||
LDD 0(%r23),%r3
|
||||
FSTD %fr25,-80(%sp)
|
||||
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
ADD %r0,%r0,%r0 ; clear the carry bit
|
||||
ADDIB,<= -4,%r26,$ENDLOOP ; actually happens in cycle 12
|
||||
FSTD %fr27,-48(%sp)
|
||||
; MFCTL %cr16,%r21 ; for timing
|
||||
; STD %r21,-112(%sp)
|
||||
|
||||
; Here is the loop.
|
||||
|
||||
$LOOP XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
ADD,DC %r29,%r4,%r4
|
||||
FSTD %fr30,-56(%sp)
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
ADD,DC %r21,%r4,%r28
|
||||
FSTD %fr29,-72(%sp)
|
||||
LDD -96(%sp),%r3
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
ADD,DC %r20,%r31,%r22
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
|
||||
ADD %r21,%r3,%r3
|
||||
LDD -56(%sp),%r20
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -88(%sp),%r4
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
ADD,DC %r0,%r0,%r20 ; Cycle 8
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
FLDD EIGHT(%r24),%fr28
|
||||
LDD -104(%sp),%r31
|
||||
|
||||
SHRPD %r20,%r19,32,%r20 ; Cycle 9
|
||||
ADD %r21,%r1,%r1
|
||||
STD %r28,UN_EIGHT(%r23)
|
||||
LDD -72(%sp),%r29
|
||||
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
ADD,DC %r3,%r4,%r4
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr25,-80(%sp)
|
||||
LDD 0(%r23),%r3
|
||||
|
||||
LDO SIXTEEN(%r24),%r24 ; Cycle 12
|
||||
FSTD %fr31,-64(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
ADD %r22,%r1,%r1
|
||||
ADDIB,> -2,%r26,$LOOP ; actually happens in cycle 12
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
$ENDLOOP
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
; MFCTL %cr16,%r21 ; for timing
|
||||
; STD %r21,UN_SIXTEEN(%r23)
|
||||
; LDD -112(%sp),%r21
|
||||
; STD %r21,UN_EIGHT(%r23)
|
||||
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
ADD,DC %r29,%r4,%r4
|
||||
CMPIB,= 0,%r26,$ONEMORE
|
||||
FSTD %fr30,-56(%sp)
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
ADD %r3,%r1,%r1 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
FSTD %fr29,-72(%sp)
|
||||
STD %r28,UN_EIGHT(%r23) ; moved up from cycle 9
|
||||
LDD -96(%sp),%r3
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
$JOIN4
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
ADD %r21,%r3,%r3 ; Cycle 6
|
||||
LDD -56(%sp),%r20
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -88(%sp),%r4
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
ADD,DC %r0,%r0,%r20 ; Cycle 8
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
LDD -104(%sp),%r31
|
||||
|
||||
SHRPD %r20,%r19,32,%r20 ; Cycle 9
|
||||
ADD %r21,%r1,%r1
|
||||
LDD -72(%sp),%r29
|
||||
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 11
|
||||
LDD 0(%r23),%r3
|
||||
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
ADD,DC %r29,%r4,%r4 ; Cycle 1
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
|
||||
STD %r1,UN_SIXTEEN(%r23); Cycle 6
|
||||
|
||||
STD %r28,UN_EIGHT(%r23) ; Cycle 9
|
||||
|
||||
LDD 0(%r23),%r3 ; Cycle 11
|
||||
|
||||
; Shutdown code, third stage.
|
||||
|
||||
LDO SIXTEEN(%r23),%r23
|
||||
ADD %r3,%r22,%r1
|
||||
$JOIN1 ADD,DC %r0,%r0,%r21
|
||||
CMPIB,*= 0,%r21,$L0 ; if no overflow, exit
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FINAL1 LDO EIGHT(%r23),%r23
|
||||
LDD UN_SIXTEEN(%r23),%r21
|
||||
ADDI 1,%r21,%r21
|
||||
CMPIB,*= 0,%r21,$FINAL1 ; Keep looping if there is a carry.
|
||||
STD %r21,UN_SIXTEEN(%r23)
|
||||
B $L0
|
||||
NOP
|
||||
|
||||
; Here is the code that handles the difficult cases N=1, N=2, and N=3.
|
||||
; We do the usual trick -- branch out of the startup code at appropriate
|
||||
; points, and branch into the shutdown code.
|
||||
|
||||
$N_IS_SMALL
|
||||
CMPIB,= 0,%r26,$N_IS_ONE
|
||||
FSTD %fr24,-96(%sp) ; Cycle 10
|
||||
FLDD EIGHT(%r24),%fr28 ; Cycle 8
|
||||
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
|
||||
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
|
||||
FSTD %fr25,-80(%sp)
|
||||
FSTD %fr31,-64(%sp) ; Cycle 12
|
||||
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
|
||||
CMPIB,= 2,%r26,$N_IS_THREE
|
||||
FSTD %fr30,-56(%sp)
|
||||
|
||||
; N = 2
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
FSTD %fr28,-104(%sp) ; Cycle 3
|
||||
LDD -96(%sp),%r3 ; Cycle 4
|
||||
FSTD %fr29,-72(%sp)
|
||||
B $JOIN4
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
$N_IS_THREE
|
||||
FLDD SIXTEEN(%r24),%fr24
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
B $JOIN3
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
$N_IS_ONE
|
||||
FSTD %fr25,-80(%sp)
|
||||
FSTD %fr27,-48(%sp)
|
||||
FSTD %fr26,-88(%sp) ; Cycle 2
|
||||
B $JOIN5
|
||||
ADD %r0,%r0,%r22
|
||||
|
||||
; We came out of the unrolled loop with wrong parity. Do one more
|
||||
; single cycle. This is quite tricky, because of the way the
|
||||
; carry chains and SHRPD chains have been chopped up.
|
||||
|
||||
$ONEMORE
|
||||
|
||||
FLDD 0(%r24),%fr24
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
|
||||
FSTD %fr28,-104(%sp)
|
||||
LDD UN_EIGHT(%r23),%r21
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
|
||||
ADD,DC %r21,%r4,%r28
|
||||
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
|
||||
LDD -96(%sp),%r3
|
||||
FSTD %fr29,-72(%sp)
|
||||
|
||||
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
|
||||
ADD,DC %r20,%r31,%r22
|
||||
LDD -64(%sp),%r19
|
||||
LDD -80(%sp),%r21
|
||||
|
||||
STD %r1,UN_SIXTEEN(%r23); Cycle 6
|
||||
$JOIN3
|
||||
XMPYU %fr9L,%fr24R,%fr24
|
||||
LDD -56(%sp),%r20
|
||||
ADD %r21,%r3,%r3
|
||||
|
||||
ADD,DC %r20,%r19,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
|
||||
LDD -104(%sp),%r31 ; Cycle 8
|
||||
ADD,DC %r0,%r0,%r20
|
||||
SHRPD %r19,%r3,32,%r3
|
||||
|
||||
LDD -72(%sp),%r29 ; Cycle 9
|
||||
SHRPD %r20,%r19,32,%r20
|
||||
ADD %r21,%r1,%r1
|
||||
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
FSTD %fr24,-96(%sp)
|
||||
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 11
|
||||
LDD 0(%r23),%r3
|
||||
FSTD %fr25,-80(%sp)
|
||||
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
FSTD %fr27,-48(%sp)
|
||||
|
||||
; Shutdown code, stage 1-1/2.
|
||||
|
||||
ADD,DC %r29,%r4,%r4 ; Cycle 1
|
||||
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
ADD,DC %r0,%r20,%r20
|
||||
FSTD %fr26,-88(%sp)
|
||||
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
|
||||
ADD,DC %r21,%r4,%r28 ; Cycle 4
|
||||
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
|
||||
|
||||
ADD,DC %r20,%r31,%r22 ; Cycle 5
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
$JOIN5
|
||||
LDD -96(%sp),%r3 ; moved from cycle 4
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r21,%r3,%r3 ; Cycle 6
|
||||
ADD,DC %r0,%r0,%r19 ; Cycle 7
|
||||
LDD -88(%sp),%r4
|
||||
SHRPD %r3,%r0,32,%r21
|
||||
LDD -48(%sp),%r1
|
||||
SHRPD %r19,%r3,32,%r3 ; Cycle 8
|
||||
ADD %r21,%r1,%r1 ; Cycle 9
|
||||
ADD,DC %r3,%r4,%r4 ; Cycle 10
|
||||
LDD 0(%r23),%r3 ; Cycle 11
|
||||
ADD %r22,%r1,%r1 ; Cycle 13
|
||||
|
||||
; Shutdown code, stage 2-1/2.
|
||||
|
||||
ADD,DC %r0,%r4,%r4 ; Cycle 1
|
||||
LDO SIXTEEN(%r23),%r23 ; Cycle 2
|
||||
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
|
||||
ADD %r3,%r1,%r1
|
||||
STD %r1,UN_SIXTEEN(%r23)
|
||||
ADD,DC %r21,%r4,%r1
|
||||
B $JOIN1
|
||||
LDO EIGHT(%r23),%r23
|
||||
|
||||
; exit
|
||||
|
||||
$L0
|
||||
.LEAVE
|
||||
|
||||
; We have verified that the above command generates what we want:
|
||||
; LDW -124(%sp),%r4
|
||||
; BVE (%r2)
|
||||
; LDW,MB -128(%sp),%r3
|
||||
|
||||
.PROCEND
|
||||
|
||||
; ***************************************************************
|
||||
;
|
||||
; add_diag_[little/big]
|
||||
;
|
||||
; ***************************************************************
|
||||
|
||||
; The arguments are as follows:
|
||||
; r2 return PC, of course
|
||||
; r26 = arg1 = length
|
||||
; r25 = arg2 = vector to square
|
||||
; r24 = arg3 = result vector
|
||||
|
||||
#ifdef LITTLE_WORDIAN
|
||||
add_diag_little
|
||||
#else
|
||||
add_diag_big
|
||||
#endif
|
||||
.PROC
|
||||
.CALLINFO FRAME=120,ENTRY_GR=%r4
|
||||
.ENTER
|
||||
|
||||
ADDIB,< -1,%r26,$Z0 ; If N=0, exit immediately.
|
||||
NOP
|
||||
|
||||
; Startup code
|
||||
|
||||
FLDD 0(%r25),%fr7 ; Cycle 2 (alternate body)
|
||||
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
|
||||
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDO SIXTEEN(%r25),%r25 ; Cycle 6
|
||||
FSTD %fr29,-88(%sp)
|
||||
FSTD %fr27,-72(%sp) ; Cycle 7
|
||||
CMPIB,= 0,%r26,$DIAG_N_IS_ONE ; Cycle 1 (main body)
|
||||
FSTD %fr30,-96(%sp)
|
||||
FLDD UN_EIGHT(%r25),%fr7 ; Cycle 2
|
||||
LDD -88(%sp),%r22 ; Cycle 3
|
||||
LDD -72(%sp),%r31 ; Cycle 4
|
||||
XMPYU %fr7R,%fr7R,%fr28
|
||||
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr31
|
||||
LDD -96(%sp),%r20 ; Cycle 6
|
||||
FSTD %fr28,-80(%sp)
|
||||
ADD %r0,%r0,%r0 ; clear the carry bit
|
||||
ADDIB,<= -2,%r26,$ENDDIAGLOOP ; Cycle 7
|
||||
FSTD %fr24,-64(%sp)
|
||||
|
||||
; Here is the loop. It is unrolled twice, modelled after the "alternate body" and then the "main body".
|
||||
|
||||
$DIAGLOOP
|
||||
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
|
||||
LDO SIXTEEN(%r25),%r25
|
||||
LDD 0(%r24),%r1
|
||||
FSTD %fr31,-104(%sp)
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD,DC %r22,%r3,%r3
|
||||
FLDD UN_SIXTEEN(%r25),%fr7
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
ADD %r1,%r3,%r3
|
||||
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
|
||||
LDD -80(%sp),%r21
|
||||
STD %r3,0(%r24)
|
||||
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDD -64(%sp),%r29
|
||||
LDD EIGHT(%r24),%r1
|
||||
ADD,DC %r4,%r20,%r20 ; Cycle 6
|
||||
LDD -104(%sp),%r19
|
||||
FSTD %fr29,-88(%sp)
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
FSTD %fr27,-72(%sp)
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
LDD UN_SIXTEEN(%r24),%r28
|
||||
FSTD %fr30,-96(%sp)
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD,DC %r21,%r4,%r4
|
||||
FLDD UN_EIGHT(%r25),%fr7
|
||||
STD %r1,UN_TWENTY_FOUR(%r24)
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
ADD %r28,%r4,%r4
|
||||
XMPYU %fr7R,%fr7R,%fr28 ; Cycle 4
|
||||
LDD -88(%sp),%r22
|
||||
STD %r4,UN_SIXTEEN(%r24)
|
||||
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7L,%fr31
|
||||
LDD -72(%sp),%r31
|
||||
LDD UN_EIGHT(%r24),%r28
|
||||
ADD,DC %r3,%r19,%r19 ; Cycle 6
|
||||
LDD -96(%sp),%r20
|
||||
FSTD %fr28,-80(%sp)
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
FSTD %fr24,-64(%sp)
|
||||
ADDIB,> -2,%r26,$DIAGLOOP ; Cycle 8
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
$ENDDIAGLOOP
|
||||
|
||||
ADD,DC %r0,%r22,%r22
|
||||
CMPIB,= 0,%r26,$ONEMOREDIAG
|
||||
SHRPD %r31,%r0,31,%r3
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r3,%r28,%r3
|
||||
LDD -64(%sp),%r29 ; Cycle 4
|
||||
STD %r3,0(%r24)
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
LDO SIXTEEN(%r25),%r25 ; Cycle 6
|
||||
LDD -104(%sp),%r19
|
||||
ADD,DC %r4,%r20,%r20
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
ADD,DC %r0,%r21,%r21 ; Cycle 8
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
LDD UN_SIXTEEN(%r24),%r1
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD %r4,%r21,%r4
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
ADD %r4,%r1,%r4
|
||||
STD %r4,UN_SIXTEEN(%r24); Cycle 4
|
||||
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
|
||||
ADD,DC %r3,%r19,%r19 ; Cycle 6
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
ADD,DC %r0,%r0,%r22 ; Cycle 8
|
||||
CMPIB,*= 0,%r22,$Z0 ; if no overflow, exit
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FDIAG2
|
||||
LDO EIGHT(%r24),%r24
|
||||
LDD UN_EIGHT(%r24),%r26
|
||||
ADDI 1,%r26,%r26
|
||||
CMPIB,*= 0,%r26,$FDIAG2 ; Keep looping if there is a carry.
|
||||
STD %r26,UN_EIGHT(%r24)
|
||||
|
||||
B $Z0
|
||||
NOP
|
||||
|
||||
; Here is the code that handles the difficult case N=1.
|
||||
; We do the usual trick -- branch out of the startup code at appropriate
|
||||
; points, and branch into the shutdown code.
|
||||
|
||||
$DIAG_N_IS_ONE
|
||||
|
||||
LDD -88(%sp),%r22
|
||||
LDD -72(%sp),%r31
|
||||
B $JOINDIAG
|
||||
LDD -96(%sp),%r20
|
||||
|
||||
; We came out of the unrolled loop with wrong parity. Do one more
|
||||
; single cycle. This is the "alternate body". It will, of course,
|
||||
; give us opposite registers from the other case, so we need
|
||||
; completely different shutdown code.
|
||||
|
||||
$ONEMOREDIAG
|
||||
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
FLDD 0(%r25),%fr7 ; Cycle 2
|
||||
SHRPD %r0,%r31,31,%r4
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
LDD -80(%sp),%r21
|
||||
ADD %r3,%r28,%r3
|
||||
LDD -64(%sp),%r29 ; Cycle 4
|
||||
STD %r3,0(%r24)
|
||||
XMPYU %fr7R,%fr7R,%fr29
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
XMPYU %fr7L,%fr7R,%fr27
|
||||
XMPYU %fr7L,%fr7L,%fr30
|
||||
LDD -104(%sp),%r19 ; Cycle 6
|
||||
FSTD %fr29,-88(%sp)
|
||||
ADD,DC %r4,%r20,%r20
|
||||
FSTD %fr27,-72(%sp) ; Cycle 7
|
||||
ADD %r20,%r1,%r1
|
||||
ADD,DC %r0,%r21,%r21 ; Cycle 8
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Shutdown code, first stage.
|
||||
|
||||
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
|
||||
LDO THIRTY_TWO(%r24),%r24
|
||||
FSTD %fr30,-96(%sp)
|
||||
LDD UN_SIXTEEN(%r24),%r1
|
||||
SHRPD %r0,%r29,31,%r3 ; Cycle 2
|
||||
ADD %r4,%r21,%r4
|
||||
ADD,DC %r0,%r19,%r19 ; Cycle 3
|
||||
LDD -88(%sp),%r22
|
||||
ADD %r4,%r1,%r4
|
||||
LDD -72(%sp),%r31 ; Cycle 4
|
||||
STD %r4,UN_SIXTEEN(%r24)
|
||||
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
|
||||
LDD -96(%sp),%r20 ; Cycle 6
|
||||
ADD,DC %r3,%r19,%r19
|
||||
ADD %r19,%r28,%r28 ; Cycle 7
|
||||
ADD,DC %r0,%r22,%r22 ; Cycle 8
|
||||
STD %r28,UN_EIGHT(%r24)
|
||||
|
||||
; Shutdown code, second stage.
|
||||
|
||||
$JOINDIAG
|
||||
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
|
||||
LDD 0(%r24),%r28
|
||||
SHRPD %r0,%r31,31,%r4 ; Cycle 2
|
||||
ADD %r3,%r22,%r3
|
||||
ADD,DC %r0,%r20,%r20 ; Cycle 3
|
||||
ADD %r3,%r28,%r3
|
||||
STD %r3,0(%r24) ; Cycle 4
|
||||
LDD EIGHT(%r24),%r1 ; Cycle 5
|
||||
ADD,DC %r4,%r20,%r20
|
||||
ADD %r20,%r1,%r1 ; Cycle 7
|
||||
ADD,DC %r0,%r0,%r21 ; Cycle 8
|
||||
CMPIB,*= 0,%r21,$Z0 ; if no overflow, exit
|
||||
STD %r1,EIGHT(%r24)
|
||||
|
||||
; Final carry propagation
|
||||
|
||||
$FDIAG1
|
||||
LDO EIGHT(%r24),%r24
|
||||
LDD EIGHT(%r24),%r26
|
||||
ADDI 1,%r26,%r26
|
||||
CMPIB,*= 0,%r26,$FDIAG1 ; Keep looping if there is a carry.
|
||||
STD %r26,EIGHT(%r24)
|
||||
|
||||
$Z0
|
||||
.LEAVE
|
||||
.PROCEND
|
||||
; .ALLOW
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
#ifdef LITTLE_WORDIAN
|
||||
.EXPORT maxpy_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
|
||||
.EXPORT add_diag_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
|
||||
#else
|
||||
.EXPORT maxpy_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
|
||||
.EXPORT add_diag_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
|
||||
#endif
|
||||
.END
|
||||
|
||||
|
||||
; How to use "maxpy_PA20_little" and "maxpy_PA20_big"
|
||||
;
|
||||
; The routine "maxpy_PA20_little" or "maxpy_PA20_big"
|
||||
; performs a 64-bit x any-size multiply, and adds the
|
||||
; result to an area of memory. That is, it performs
|
||||
; something like
|
||||
;
|
||||
; A B C D
|
||||
; * Z
|
||||
; __________
|
||||
; P Q R S T
|
||||
;
|
||||
; and then adds the "PQRST" vector into an area of memory,
|
||||
; handling all carries.
|
||||
;
|
||||
; Digression on nomenclature and endian-ness:
|
||||
;
|
||||
; Each of the capital letters in the above represents a 64-bit
|
||||
; quantity. That is, you could think of the discussion as
|
||||
; being in terms of radix-16-quintillion arithmetic. The data
|
||||
; type being manipulated is "unsigned long long int". This
|
||||
; requires the 64-bit extension of the HP-UX C compiler,
|
||||
; available at release 10. You need these compiler flags to
|
||||
; enable these extensions:
|
||||
;
|
||||
; -Aa +e +DA2.0 +DS2.0
|
||||
;
|
||||
; (The first specifies ANSI C, the second enables the
|
||||
; extensions, which are beyond ANSI C, and the third and
|
||||
; fourth tell the compiler to use whatever features of the
|
||||
; PA2.0 architecture it wishes, in order to made the code more
|
||||
; efficient. Since the presence of the assembly code will
|
||||
; make the program unable to run on anything less than PA2.0,
|
||||
; you might as well gain the performance enhancements in the C
|
||||
; code as well.)
|
||||
;
|
||||
; Questions of "endian-ness" often come up, usually in the
|
||||
; context of byte ordering in a word. These routines have a
|
||||
; similar issue, that could be called "wordian-ness".
|
||||
; Independent of byte ordering (PA is always big-endian), one
|
||||
; can make two choices when representing extremely large
|
||||
; numbers as arrays of 64-bit doublewords in memory.
|
||||
;
|
||||
; "Little-wordian" layout means that the least significant
|
||||
; word of a number is stored at the lowest address.
|
||||
;
|
||||
; MSW LSW
|
||||
; | |
|
||||
; V V
|
||||
;
|
||||
; A B C D E
|
||||
;
|
||||
; ^ ^ ^
|
||||
; | | |____ address 0
|
||||
; | |
|
||||
; | |_______address 8
|
||||
; |
|
||||
; address 32
|
||||
;
|
||||
; "Big-wordian" means that the most significant word is at the
|
||||
; lowest address.
|
||||
;
|
||||
; MSW LSW
|
||||
; | |
|
||||
; V V
|
||||
;
|
||||
; A B C D E
|
||||
;
|
||||
; ^ ^ ^
|
||||
; | | |____ address 32
|
||||
; | |
|
||||
; | |_______address 24
|
||||
; |
|
||||
; address 0
|
||||
;
|
||||
; When you compile the file, you must specify one or the other, with
|
||||
; a switch "-DLITTLE_WORDIAN" or "-DBIG_WORDIAN".
|
||||
;
|
||||
; Incidentally, you assemble this file as part of your
|
||||
; project with the same C compiler as the rest of the program.
|
||||
; My "makefile" for a superprecision arithmetic package has
|
||||
; the following stuff:
|
||||
;
|
||||
; # definitions:
|
||||
; CC = cc -Aa +e -z +DA2.0 +DS2.0 +w1
|
||||
; CFLAGS = +O3
|
||||
; LDFLAGS = -L /usr/lib -Wl,-aarchive
|
||||
;
|
||||
; # general build rule for ".s" files:
|
||||
; .s.o:
|
||||
; $(CC) $(CFLAGS) -c $< -DBIG_WORDIAN
|
||||
;
|
||||
; # Now any bind step that calls for pa20.o will assemble pa20.s
|
||||
;
|
||||
; End of digression, back to arithmetic:
|
||||
;
|
||||
; The way we multiply two huge numbers is, of course, to multiply
|
||||
; the "ABCD" vector by each of the "WXYZ" doublewords, adding
|
||||
; the result vectors with increasing offsets, the way we learned
|
||||
; in school, back before we all used calculators:
|
||||
;
|
||||
; A B C D
|
||||
; * W X Y Z
|
||||
; __________
|
||||
; P Q R S T
|
||||
; E F G H I
|
||||
; M N O P Q
|
||||
; + R S T U V
|
||||
; _______________
|
||||
; F I N A L S U M
|
||||
;
|
||||
; So we call maxpy_PA20_big (in my case; my package is
|
||||
; big-wordian) repeatedly, giving the W, X, Y, and Z arguments
|
||||
; in turn as the "scalar", and giving the "ABCD" vector each
|
||||
; time. We direct it to add its result into an area of memory
|
||||
; that we have cleared at the start. We skew the exact
|
||||
; location into that area with each call.
|
||||
;
|
||||
; The prototype for the function is
|
||||
;
|
||||
; extern void maxpy_PA20_big(
|
||||
; int length, /* Number of doublewords in the multiplicand vector. */
|
||||
; const long long int *scalaraddr, /* Address to fetch the scalar. */
|
||||
; const long long int *multiplicand, /* The multiplicand vector. */
|
||||
; long long int *result); /* Where to accumulate the result. */
|
||||
;
|
||||
; (You should place a copy of this prototype in an include file
|
||||
; or in your C file.)
|
||||
;
|
||||
; Now, IN ALL CASES, the given address for the multiplicand or
|
||||
; the result is that of the LEAST SIGNIFICANT DOUBLEWORD.
|
||||
; That word is, of course, the word at which the routine
|
||||
; starts processing. "maxpy_PA20_little" then increases the
|
||||
; addresses as it computes. "maxpy_PA20_big" decreases them.
|
||||
;
|
||||
; In our example above, "length" would be 4 in each case.
|
||||
; "multiplicand" would be the "ABCD" vector. Specifically,
|
||||
; the address of the element "D". "scalaraddr" would be the
|
||||
; address of "W", "X", "Y", or "Z" on the four calls that we
|
||||
; would make. (The order doesn't matter, of course.)
|
||||
; "result" would be the appropriate address in the result
|
||||
; area. When multiplying by "Z", that would be the least
|
||||
; significant word. When multiplying by "Y", it would be the
|
||||
; next higher word (8 bytes higher if little-wordian; 8 bytes
|
||||
; lower if big-wordian), and so on. The size of the result
|
||||
; area must be the the sum of the sizes of the multiplicand
|
||||
; and multiplier vectors, and must be initialized to zero
|
||||
; before we start.
|
||||
;
|
||||
; Whenever the routine adds its partial product into the result
|
||||
; vector, it follows carry chains as far as they need to go.
|
||||
;
|
||||
; Here is the super-precision multiply routine that I use for
|
||||
; my package. The package is big-wordian. I have taken out
|
||||
; handling of exponents (it's a floating point package):
|
||||
;
|
||||
; static void mul_PA20(
|
||||
; int size,
|
||||
; const long long int *arg1,
|
||||
; const long long int *arg2,
|
||||
; long long int *result)
|
||||
; {
|
||||
; int i;
|
||||
;
|
||||
; for (i=0 ; i<2*size ; i++) result[i] = 0ULL;
|
||||
;
|
||||
; for (i=0 ; i<size ; i++) {
|
||||
; maxpy_PA20_big(size, &arg2[i], &arg1[size-1], &result[size+i]);
|
||||
; }
|
||||
; }
|
||||
@@ -1,54 +0,0 @@
|
||||
#/bin/sh
|
||||
#
|
||||
# ***** 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 script to change the system id in an object file from PA-RISC 2.0 to 1.1.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Hewlett-Packard Company.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1999
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# wrapped by Dennis Handly on Tue Mar 23 15:23:43 1999
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
# script to change the system id in an object file from PA-RISC 2.0 to 1.1
|
||||
|
||||
adb -w $1 << EOF
|
||||
?m 0 -1 0
|
||||
0x0?X
|
||||
0x0?W (@0x0&~0x40000)|(~@0x0&0x40000)
|
||||
|
||||
0?"change checksum"
|
||||
0x7c?X
|
||||
0x7c?W (@0x7c&~0x40000)|(~@0x7c&0x40000)
|
||||
$q
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* logtab.h
|
||||
*
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* 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 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 ***** */
|
||||
/* $Id: logtab.h,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
const float s_logv_2[] = {
|
||||
0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */
|
||||
0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */
|
||||
0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */
|
||||
0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */
|
||||
0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */
|
||||
0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */
|
||||
0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */
|
||||
0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */
|
||||
0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */
|
||||
0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */
|
||||
0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */
|
||||
0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */
|
||||
0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */
|
||||
0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */
|
||||
0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */
|
||||
0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */
|
||||
0.166666667f
|
||||
};
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/usr/linguist/bin/perl
|
||||
|
||||
#
|
||||
# make-logtab
|
||||
#
|
||||
# Generate a table of logarithms of 2 in various bases, for use in
|
||||
# estimating the output sizes of various bases.
|
||||
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic
|
||||
# library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
# 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 *****
|
||||
|
||||
# $Id: make-logtab,v 1.4 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
$ARRAYNAME = $ENV{'ARRAYNAME'} || "s_logv_2";
|
||||
$ARRAYTYPE = $ENV{'ARRAYTYPE'} || "float";
|
||||
|
||||
printf("const %s %s[] = {\n %0.9ff, %0.9ff, ",
|
||||
$ARRAYTYPE, $ARRAYNAME, 0, 0);
|
||||
$brk = 2;
|
||||
for($ix = 2; $ix < 64; $ix++) {
|
||||
printf("%0.9ff, ", (log(2)/log($ix)));
|
||||
$brk = ($brk + 1) & 3;
|
||||
if(!$brk) {
|
||||
printf(" /* %2d %2d %2d %2d */\n ",
|
||||
$ix - 3, $ix - 2, $ix - 1, $ix);
|
||||
}
|
||||
}
|
||||
printf("%0.9ff\n};\n\n", (log(2)/log($ix)));
|
||||
|
||||
exit 0;
|
||||
@@ -1,133 +0,0 @@
|
||||
#!/usr/linguist/bin/perl
|
||||
|
||||
#
|
||||
# make-test-arrays
|
||||
#
|
||||
# Given a test-arrays file, which specifies the test suite names, the
|
||||
# names of the functions which perform those test suites, and
|
||||
# descriptive comments, this script generates C structures for the
|
||||
# mpi-test program. The input consists of lines of the form:
|
||||
#
|
||||
# suite-name:function-name:comment
|
||||
#
|
||||
# The output is written to the standard output. Blank lines are
|
||||
# ignored, and comments beginning with '#' are stripped.
|
||||
|
||||
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# 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 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 *****
|
||||
|
||||
# $Id: make-test-arrays,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
# Read parameters from the environment, if available
|
||||
$NAMEVAR = $ENV{'NAMEVAR'} || "g_names";
|
||||
$COUNTVAR = $ENV{'COUNTVAR'} || "g_count";
|
||||
$FUNCVAR = $ENV{'FUNCVAR'} || "g_tests";
|
||||
$DESCVAR = $ENV{'DESCVAR'} || "g_descs";
|
||||
$FUNCLEN = 13;
|
||||
$NAMELEN = 18;
|
||||
$DESCLEN = 45;
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Suck in input from the files on the command line, or standard input
|
||||
while(<>) {
|
||||
chomp;
|
||||
s/\#.*$//;
|
||||
next if /^\s*$/;
|
||||
|
||||
($suite, $func, $desc) = split(/:/, $_);
|
||||
|
||||
$tmp = { "suite" => $suite,
|
||||
"func" => $func,
|
||||
"desc" => $desc };
|
||||
|
||||
push(@item, $tmp);
|
||||
}
|
||||
$count = scalar(@item);
|
||||
$last = pop(@item);
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of names
|
||||
print "/* Table mapping test suite names to index numbers */\n";
|
||||
printf("const int %s = %d;\n", $COUNTVAR, $count);
|
||||
printf("const char *%s[] = {\n", $NAMEVAR);
|
||||
|
||||
foreach $elt (@item) {
|
||||
printf(" \"%s\",%s/* %s%s */\n", $elt->{"suite"},
|
||||
" " x ($NAMELEN - length($elt->{"suite"})),
|
||||
$elt->{"desc"},
|
||||
" " x ($DESCLEN - length($elt->{"desc"})));
|
||||
}
|
||||
printf(" \"%s\" %s/* %s%s */\n", $last->{"suite"},
|
||||
" " x ($NAMELEN - length($last->{"suite"})),
|
||||
$last->{"desc"},
|
||||
" " x ($DESCLEN - length($last->{"desc"})));
|
||||
print "};\n\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the driver function prototypes
|
||||
print "/* Test function prototypes */\n";
|
||||
foreach $elt (@item, $last) {
|
||||
printf("int %s(void);\n", $elt->{"func"});
|
||||
}
|
||||
print "\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of functions
|
||||
print "/* Table mapping index numbers to functions */\n";
|
||||
printf("int (*%s[])(void) = {\n ", $FUNCVAR);
|
||||
$brk = 0;
|
||||
|
||||
foreach $elt (@item) {
|
||||
print($elt->{"func"}, ", ",
|
||||
" " x ($FUNCLEN - length($elt->{"func"})));
|
||||
$brk = ($brk + 1) & 3;
|
||||
print "\n " unless($brk);
|
||||
}
|
||||
print $last->{"func"}, "\n};\n\n";
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Output the table of descriptions
|
||||
print "/* Table mapping index numbers to descriptions */\n";
|
||||
printf("const char *%s[] = {\n", $DESCVAR);
|
||||
|
||||
foreach $elt (@item) {
|
||||
printf(" \"%s\",\n", $elt->{"desc"});
|
||||
}
|
||||
printf(" \"%s\"\n};\n\n", $last->{"desc"});
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/* ***** 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 Netscape security libraries.
|
||||
*
|
||||
* 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):
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
|
||||
/* #define OLD_WAY 1 */
|
||||
|
||||
/* This key is the 1024-bit test key used for speed testing of RSA private
|
||||
** key ops.
|
||||
*/
|
||||
|
||||
#define CONST const
|
||||
|
||||
static CONST unsigned char default_n[128] = {
|
||||
0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
|
||||
0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
|
||||
0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
|
||||
0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
|
||||
0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
|
||||
0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
|
||||
0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
|
||||
0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
|
||||
};
|
||||
|
||||
static CONST unsigned char default_d[128] = {
|
||||
0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
|
||||
0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
|
||||
0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
|
||||
0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
|
||||
0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
|
||||
0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
|
||||
0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
|
||||
0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_ITERS 50
|
||||
|
||||
typedef clock_t timetype;
|
||||
#define gettime(x) *(x) = clock()
|
||||
#define subtime(a, b) a -= b
|
||||
#define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
|
||||
#define sec(x) (x / CLOCKS_PER_SEC)
|
||||
|
||||
struct TimingContextStr {
|
||||
timetype start;
|
||||
timetype end;
|
||||
timetype interval;
|
||||
|
||||
int minutes;
|
||||
int seconds;
|
||||
int millisecs;
|
||||
};
|
||||
|
||||
typedef struct TimingContextStr TimingContext;
|
||||
|
||||
TimingContext *CreateTimingContext(void)
|
||||
{
|
||||
return (TimingContext *)malloc(sizeof(TimingContext));
|
||||
}
|
||||
|
||||
void DestroyTimingContext(TimingContext *ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void TimingBegin(TimingContext *ctx)
|
||||
{
|
||||
gettime(&ctx->start);
|
||||
}
|
||||
|
||||
static void timingUpdate(TimingContext *ctx)
|
||||
{
|
||||
|
||||
ctx->millisecs = msec(ctx->interval) % 1000;
|
||||
ctx->seconds = sec(ctx->interval);
|
||||
ctx->minutes = ctx->seconds / 60;
|
||||
ctx->seconds %= 60;
|
||||
|
||||
}
|
||||
|
||||
void TimingEnd(TimingContext *ctx)
|
||||
{
|
||||
gettime(&ctx->end);
|
||||
ctx->interval = ctx->end;
|
||||
subtime(ctx->interval, ctx->start);
|
||||
timingUpdate(ctx);
|
||||
}
|
||||
|
||||
char *TimingGenerateString(TimingContext *ctx)
|
||||
{
|
||||
static char sBuf[4096];
|
||||
|
||||
sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
|
||||
ctx->seconds, ctx->millisecs);
|
||||
return sBuf;
|
||||
}
|
||||
|
||||
static void
|
||||
dumpBytes( unsigned char * b, int l)
|
||||
{
|
||||
int i;
|
||||
if (l <= 0)
|
||||
return;
|
||||
for (i = 0; i < l; ++i) {
|
||||
if (i % 16 == 0)
|
||||
printf("\t");
|
||||
printf(" %02x", b[i]);
|
||||
if (i % 16 == 15)
|
||||
printf("\n");
|
||||
}
|
||||
if ((i % 16) != 0)
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static mp_err
|
||||
testNewFuncs(const unsigned char * modulusBytes, int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
unsigned char buf[512];
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len );
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1);
|
||||
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4);
|
||||
mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
|
||||
mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
|
||||
mp_clear(&modulus);
|
||||
return mperr;
|
||||
}
|
||||
|
||||
int
|
||||
testModExp( const unsigned char * modulusBytes,
|
||||
const unsigned int expo,
|
||||
const unsigned char * input,
|
||||
unsigned char * output,
|
||||
int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
mp_int base;
|
||||
mp_int exponent;
|
||||
mp_int result;
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr += mp_init(&base);
|
||||
mperr += mp_init(&exponent);
|
||||
mperr += mp_init(&result);
|
||||
/* we initialize all mp_ints unconditionally, even if some fail.
|
||||
** This guarantees that the DIGITS pointer is valid (even if null).
|
||||
** So, mp_clear will do the right thing below.
|
||||
*/
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_read_unsigned_octets(&modulus,
|
||||
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||||
mp_set(&exponent, expo);
|
||||
if (mperr == MP_OKAY) {
|
||||
#if OLD_WAY
|
||||
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#else
|
||||
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#endif
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_clear(&base);
|
||||
mp_clear(&result);
|
||||
|
||||
mp_clear(&modulus);
|
||||
mp_clear(&exponent);
|
||||
|
||||
return (int)mperr;
|
||||
}
|
||||
|
||||
int
|
||||
doModExp( const unsigned char * modulusBytes,
|
||||
const unsigned char * exponentBytes,
|
||||
const unsigned char * input,
|
||||
unsigned char * output,
|
||||
int modulus_len)
|
||||
{
|
||||
mp_err mperr = MP_OKAY;
|
||||
mp_int modulus;
|
||||
mp_int base;
|
||||
mp_int exponent;
|
||||
mp_int result;
|
||||
|
||||
mperr = mp_init(&modulus);
|
||||
mperr += mp_init(&base);
|
||||
mperr += mp_init(&exponent);
|
||||
mperr += mp_init(&result);
|
||||
/* we initialize all mp_ints unconditionally, even if some fail.
|
||||
** This guarantees that the DIGITS pointer is valid (even if null).
|
||||
** So, mp_clear will do the right thing below.
|
||||
*/
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_read_unsigned_octets(&modulus,
|
||||
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len );
|
||||
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||||
if (mperr == MP_OKAY) {
|
||||
#if OLD_WAY
|
||||
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#else
|
||||
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||||
#endif
|
||||
if (mperr == MP_OKAY) {
|
||||
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_clear(&base);
|
||||
mp_clear(&result);
|
||||
|
||||
mp_clear(&modulus);
|
||||
mp_clear(&exponent);
|
||||
|
||||
return (int)mperr;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
TimingContext * timeCtx;
|
||||
char * progName;
|
||||
long iters = DEFAULT_ITERS;
|
||||
unsigned int modulus_len;
|
||||
int i;
|
||||
int rv;
|
||||
unsigned char buf [1024];
|
||||
unsigned char buf2[1024];
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
if (!progName)
|
||||
progName = strrchr(argv[0], '\\');
|
||||
progName = progName ? progName+1 : argv[0];
|
||||
|
||||
if (argc >= 2) {
|
||||
iters = atol(argv[1]);
|
||||
}
|
||||
|
||||
if (argc >= 3) {
|
||||
modulus_len = atol(argv[2]);
|
||||
} else
|
||||
modulus_len = sizeof default_n;
|
||||
|
||||
/* no library init function !? */
|
||||
|
||||
memset(buf, 0x41, sizeof buf);
|
||||
|
||||
if (iters < 2) {
|
||||
testNewFuncs( default_n, modulus_len);
|
||||
testNewFuncs( default_n+1, modulus_len - 1);
|
||||
testNewFuncs( default_n+2, modulus_len - 2);
|
||||
testNewFuncs( default_n+3, modulus_len - 3);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 0, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 1, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 2, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = testModExp(default_n, 3, buf, buf2, modulus_len);
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
}
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error in modexp operation:\n");
|
||||
exit(1);
|
||||
}
|
||||
dumpBytes((unsigned char *)buf2, modulus_len);
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
|
||||
timeCtx = CreateTimingContext();
|
||||
TimingBegin(timeCtx);
|
||||
i = iters;
|
||||
while (i--) {
|
||||
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error in modexp operation\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
TimingEnd(timeCtx);
|
||||
printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
|
||||
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,329 +0,0 @@
|
||||
/* ***** 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 SPARC optimized Montgomery multiply functions.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: montmulf.c,v 1.7 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define RF_INLINE_MACROS 1
|
||||
#endif
|
||||
|
||||
static const double TwoTo16=65536.0;
|
||||
static const double TwoToMinus16=1.0/65536.0;
|
||||
static const double Zero=0.0;
|
||||
static const double TwoTo32=65536.0*65536.0;
|
||||
static const double TwoToMinus32=1.0/(65536.0*65536.0);
|
||||
|
||||
#ifdef RF_INLINE_MACROS
|
||||
|
||||
double upper32(double);
|
||||
double lower32(double, double);
|
||||
double mod(double, double, double);
|
||||
|
||||
void i16_to_d16_and_d32x4(const double * /*1/(2^16)*/,
|
||||
const double * /* 2^16*/,
|
||||
const double * /* 0 */,
|
||||
double * /*result16*/,
|
||||
double * /* result32 */,
|
||||
float * /*source - should be unsigned int*
|
||||
converted to float* */);
|
||||
|
||||
#else
|
||||
#ifdef MP_USE_FLOOR
|
||||
#include <math.h>
|
||||
#else
|
||||
#define floor(d) ((double)((unsigned long long)(d)))
|
||||
#endif
|
||||
|
||||
static double upper32(double x)
|
||||
{
|
||||
return floor(x*TwoToMinus32);
|
||||
}
|
||||
|
||||
static double lower32(double x, double y)
|
||||
{
|
||||
return x-TwoTo32*floor(x*TwoToMinus32);
|
||||
}
|
||||
|
||||
static double mod(double x, double oneoverm, double m)
|
||||
{
|
||||
return x-m*floor(x*oneoverm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void cleanup(double *dt, int from, int tlen)
|
||||
{
|
||||
int i;
|
||||
double tmp,tmp1,x,x1;
|
||||
|
||||
tmp=tmp1=Zero;
|
||||
/* original code **
|
||||
for(i=2*from;i<2*tlen-2;i++)
|
||||
{
|
||||
x=dt[i];
|
||||
dt[i]=lower32(x,Zero)+tmp1;
|
||||
tmp1=tmp;
|
||||
tmp=upper32(x);
|
||||
}
|
||||
dt[tlen-2]+=tmp1;
|
||||
dt[tlen-1]+=tmp;
|
||||
**end original code ***/
|
||||
/* new code ***/
|
||||
for(i=2*from;i<2*tlen;i+=2)
|
||||
{
|
||||
x=dt[i];
|
||||
x1=dt[i+1];
|
||||
dt[i]=lower32(x,Zero)+tmp;
|
||||
dt[i+1]=lower32(x1,Zero)+tmp1;
|
||||
tmp=upper32(x);
|
||||
tmp1=upper32(x1);
|
||||
}
|
||||
/** end new code **/
|
||||
}
|
||||
|
||||
|
||||
void conv_d16_to_i32(unsigned int *i32, double *d16, long long *tmp, int ilen)
|
||||
{
|
||||
int i;
|
||||
long long t, t1, a, b, c, d;
|
||||
|
||||
t1=0;
|
||||
a=(long long)d16[0];
|
||||
b=(long long)d16[1];
|
||||
for(i=0; i<ilen-1; i++)
|
||||
{
|
||||
c=(long long)d16[2*i+2];
|
||||
t1+=(unsigned int)a;
|
||||
t=(a>>32);
|
||||
d=(long long)d16[2*i+3];
|
||||
t1+=(b&0xffff)<<16;
|
||||
t+=(b>>16)+(t1>>32);
|
||||
i32[i]=(unsigned int)t1;
|
||||
t1=t;
|
||||
a=c;
|
||||
b=d;
|
||||
}
|
||||
t1+=(unsigned int)a;
|
||||
t=(a>>32);
|
||||
t1+=(b&0xffff)<<16;
|
||||
i32[i]=(unsigned int)t1;
|
||||
}
|
||||
|
||||
void conv_i32_to_d32(double *d32, unsigned int *i32, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=0;i<len;i++) d32[i]=(double)(i32[i]);
|
||||
}
|
||||
|
||||
|
||||
void conv_i32_to_d16(double *d16, unsigned int *i32, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int a;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
a=i32[i];
|
||||
d16[2*i]=(double)(a&0xffff);
|
||||
d16[2*i+1]=(double)(a>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void conv_i32_to_d32_and_d16(double *d32, double *d16,
|
||||
unsigned int *i32, int len)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int a;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
#ifdef RF_INLINE_MACROS
|
||||
for(;i<len-3;i+=4)
|
||||
{
|
||||
i16_to_d16_and_d32x4(&TwoToMinus16, &TwoTo16, &Zero,
|
||||
&(d16[2*i]), &(d32[i]), (float *)(&(i32[i])));
|
||||
}
|
||||
#endif
|
||||
for(;i<len;i++)
|
||||
{
|
||||
a=i32[i];
|
||||
d32[i]=(double)(i32[i]);
|
||||
d16[2*i]=(double)(a&0xffff);
|
||||
d16[2*i+1]=(double)(a>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void adjust_montf_result(unsigned int *i32, unsigned int *nint, int len)
|
||||
{
|
||||
long long acc;
|
||||
int i;
|
||||
|
||||
if(i32[len]>0) i=-1;
|
||||
else
|
||||
{
|
||||
for(i=len-1; i>=0; i--)
|
||||
{
|
||||
if(i32[i]!=nint[i]) break;
|
||||
}
|
||||
}
|
||||
if((i<0)||(i32[i]>nint[i]))
|
||||
{
|
||||
acc=0;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
acc=acc+(unsigned long long)(i32[i])-(unsigned long long)(nint[i]);
|
||||
i32[i]=(unsigned int)acc;
|
||||
acc=acc>>32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** the lengths of the input arrays should be at least the following:
|
||||
** result[nlen+1], dm1[nlen], dm2[2*nlen+1], dt[4*nlen+2], dn[nlen], nint[nlen]
|
||||
** all of them should be different from one another
|
||||
**
|
||||
*/
|
||||
void mont_mulf_noconv(unsigned int *result,
|
||||
double *dm1, double *dm2, double *dt,
|
||||
double *dn, unsigned int *nint,
|
||||
int nlen, double dn0)
|
||||
{
|
||||
int i, j, jj;
|
||||
int tmp;
|
||||
double digit, m2j, nextm2j, a, b;
|
||||
double *dptmp, *pdm1, *pdm2, *pdn, *pdtj, pdn_0, pdm1_0;
|
||||
|
||||
pdm1=&(dm1[0]);
|
||||
pdm2=&(dm2[0]);
|
||||
pdn=&(dn[0]);
|
||||
pdm2[2*nlen]=Zero;
|
||||
|
||||
if (nlen!=16)
|
||||
{
|
||||
for(i=0;i<4*nlen+2;i++) dt[i]=Zero;
|
||||
|
||||
a=dt[0]=pdm1[0]*pdm2[0];
|
||||
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
|
||||
pdtj=&(dt[0]);
|
||||
for(j=jj=0;j<2*nlen;j++,jj++,pdtj++)
|
||||
{
|
||||
m2j=pdm2[j];
|
||||
a=pdtj[0]+pdn[0]*digit;
|
||||
b=pdtj[1]+pdm1[0]*pdm2[j+1]+a*TwoToMinus16;
|
||||
pdtj[1]=b;
|
||||
|
||||
#pragma pipeloop(0)
|
||||
for(i=1;i<nlen;i++)
|
||||
{
|
||||
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
|
||||
}
|
||||
if((jj==30)) {cleanup(dt,j/2+1,2*nlen+1); jj=0;}
|
||||
|
||||
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a=dt[0]=pdm1[0]*pdm2[0];
|
||||
|
||||
dt[65]= dt[64]= dt[63]= dt[62]= dt[61]= dt[60]=
|
||||
dt[59]= dt[58]= dt[57]= dt[56]= dt[55]= dt[54]=
|
||||
dt[53]= dt[52]= dt[51]= dt[50]= dt[49]= dt[48]=
|
||||
dt[47]= dt[46]= dt[45]= dt[44]= dt[43]= dt[42]=
|
||||
dt[41]= dt[40]= dt[39]= dt[38]= dt[37]= dt[36]=
|
||||
dt[35]= dt[34]= dt[33]= dt[32]= dt[31]= dt[30]=
|
||||
dt[29]= dt[28]= dt[27]= dt[26]= dt[25]= dt[24]=
|
||||
dt[23]= dt[22]= dt[21]= dt[20]= dt[19]= dt[18]=
|
||||
dt[17]= dt[16]= dt[15]= dt[14]= dt[13]= dt[12]=
|
||||
dt[11]= dt[10]= dt[ 9]= dt[ 8]= dt[ 7]= dt[ 6]=
|
||||
dt[ 5]= dt[ 4]= dt[ 3]= dt[ 2]= dt[ 1]=Zero;
|
||||
|
||||
pdn_0=pdn[0];
|
||||
pdm1_0=pdm1[0];
|
||||
|
||||
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
pdtj=&(dt[0]);
|
||||
|
||||
for(j=0;j<32;j++,pdtj++)
|
||||
{
|
||||
|
||||
m2j=pdm2[j];
|
||||
a=pdtj[0]+pdn_0*digit;
|
||||
b=pdtj[1]+pdm1_0*pdm2[j+1]+a*TwoToMinus16;
|
||||
pdtj[1]=b;
|
||||
|
||||
/**** this loop will be fully unrolled:
|
||||
for(i=1;i<16;i++)
|
||||
{
|
||||
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
|
||||
}
|
||||
*************************************/
|
||||
pdtj[2]+=pdm1[1]*m2j+pdn[1]*digit;
|
||||
pdtj[4]+=pdm1[2]*m2j+pdn[2]*digit;
|
||||
pdtj[6]+=pdm1[3]*m2j+pdn[3]*digit;
|
||||
pdtj[8]+=pdm1[4]*m2j+pdn[4]*digit;
|
||||
pdtj[10]+=pdm1[5]*m2j+pdn[5]*digit;
|
||||
pdtj[12]+=pdm1[6]*m2j+pdn[6]*digit;
|
||||
pdtj[14]+=pdm1[7]*m2j+pdn[7]*digit;
|
||||
pdtj[16]+=pdm1[8]*m2j+pdn[8]*digit;
|
||||
pdtj[18]+=pdm1[9]*m2j+pdn[9]*digit;
|
||||
pdtj[20]+=pdm1[10]*m2j+pdn[10]*digit;
|
||||
pdtj[22]+=pdm1[11]*m2j+pdn[11]*digit;
|
||||
pdtj[24]+=pdm1[12]*m2j+pdn[12]*digit;
|
||||
pdtj[26]+=pdm1[13]*m2j+pdn[13]*digit;
|
||||
pdtj[28]+=pdm1[14]*m2j+pdn[14]*digit;
|
||||
pdtj[30]+=pdm1[15]*m2j+pdn[15]*digit;
|
||||
/* no need for cleenup, cannot overflow */
|
||||
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
|
||||
}
|
||||
}
|
||||
|
||||
conv_d16_to_i32(result,dt+2*nlen,(long long *)dt,nlen+1);
|
||||
|
||||
adjust_montf_result(result,nint,nlen);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/* ***** 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 interface file for SPARC Montgomery multiply functions.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: montmulf.h,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* The functions that are to be called from outside of the .s file have the
|
||||
* following interfaces and array size requirements:
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d32(double *d32, unsigned int *i32, int len);
|
||||
|
||||
/* Converts an array of int's to an array of doubles, so that each double
|
||||
* corresponds to an int. len is the number of items converted.
|
||||
* Does not allocate the output array.
|
||||
* The pointers d32 and i32 should point to arrays of size at least len
|
||||
* (doubles and unsigned ints, respectively)
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d16(double *d16, unsigned int *i32, int len);
|
||||
|
||||
/* Converts an array of int's to an array of doubles so that each element
|
||||
* of the int array is converted to a pair of doubles, the first one
|
||||
* corresponding to the lower (least significant) 16 bits of the int and
|
||||
* the second one corresponding to the upper (most significant) 16 bits of
|
||||
* the 32-bit int. len is the number of ints converted.
|
||||
* Does not allocate the output array.
|
||||
* The pointer d16 should point to an array of doubles of size at least
|
||||
* 2*len and i32 should point an array of ints of size at least len
|
||||
*/
|
||||
|
||||
|
||||
void conv_i32_to_d32_and_d16(double *d32, double *d16,
|
||||
unsigned int *i32, int len);
|
||||
|
||||
/* Does the above two conversions together, it is much faster than doing
|
||||
* both of those in succession
|
||||
*/
|
||||
|
||||
|
||||
void mont_mulf_noconv(unsigned int *result,
|
||||
double *dm1, double *dm2, double *dt,
|
||||
double *dn, unsigned int *nint,
|
||||
int nlen, double dn0);
|
||||
|
||||
/* Does the Montgomery multiplication of the numbers stored in the arrays
|
||||
* pointed to by dm1 and dm2, writing the result to the array pointed to by
|
||||
* result. It uses the array pointed to by dt as a temporary work area.
|
||||
* nint should point to the modulus in the array-of-integers representation,
|
||||
* dn should point to its array-of-doubles as obtained as a result of the
|
||||
* function call conv_i32_to_d32(dn, nint, nlen);
|
||||
* nlen is the length of the array containing the modulus.
|
||||
* The representation used for dm1 is the one that is a result of the function
|
||||
* call conv_i32_to_d32(dm1, m1, nlen), the representation for dm2 is the
|
||||
* result of the function call conv_i32_to_d16(dm2, m2, nlen).
|
||||
* Note that m1 and m2 should both be of length nlen, so they should be
|
||||
* padded with 0's if necessary before the conversion. The result comes in
|
||||
* this form (int representation, padded with 0's).
|
||||
* dn0 is the value of the 16 least significant bits of n0'.
|
||||
* The function does not allocate memory for any of the arrays, so the
|
||||
* pointers should point to arrays with the following minimal sizes:
|
||||
* result - nlen+1
|
||||
* dm1 - nlen
|
||||
* dm2 - 2*nlen+1 ( the +1 is necessary for technical reasons )
|
||||
* dt - 4*nlen+2
|
||||
* dn - nlen
|
||||
* nint - nlen
|
||||
* No two arrays should point to overlapping areas of memory.
|
||||
*/
|
||||
@@ -1,141 +0,0 @@
|
||||
!
|
||||
! ***** 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 inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! 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 *****
|
||||
! $Id: montmulf.il,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
|
||||
fdtox %f10,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f12
|
||||
|
||||
fdtox %f10,%f10
|
||||
fmovs %f12,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f2
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f4
|
||||
std %o4,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f6
|
||||
|
||||
fmuld %f2,%f4,%f4
|
||||
fdtox %f4,%f4
|
||||
fxtod %f4,%f4
|
||||
fmuld %f4,%f6,%f4
|
||||
fsubd %f2,%f4,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,141 +0,0 @@
|
||||
!
|
||||
! ***** 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 inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! 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 *****
|
||||
! $Id: montmulfv8.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
|
||||
fdtox %f10,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f10
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f12
|
||||
|
||||
fdtox %f10,%f10
|
||||
fmovs %f12,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
std %o0,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f2
|
||||
std %o2,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f4
|
||||
std %o4,[%sp+0x48]
|
||||
ldd [%sp+0x48],%f6
|
||||
|
||||
fmuld %f2,%f4,%f4
|
||||
fdtox %f4,%f4
|
||||
fxtod %f4,%f4
|
||||
fmuld %f4,%f6,%f4
|
||||
fsubd %f2,%f4,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
!
|
||||
! ***** 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 inline macros for SPARC Montgomery multiply functions.
|
||||
!
|
||||
! The Initial Developer of the Original Code is
|
||||
! Sun Microsystems Inc.
|
||||
! Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
! 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 *****
|
||||
! $Id: montmulfv9.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
|
||||
|
||||
!
|
||||
! double upper32(double /*frs1*/);
|
||||
!
|
||||
.inline upper32,8
|
||||
fdtox %f0,%f10
|
||||
fitod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double lower32(double /*frs1*/, double /* Zero */);
|
||||
!
|
||||
.inline lower32,8
|
||||
fdtox %f0,%f10
|
||||
fmovs %f2,%f10
|
||||
fxtod %f10,%f0
|
||||
.end
|
||||
|
||||
!
|
||||
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
|
||||
!
|
||||
.inline mod,12
|
||||
fmuld %f0,%f2,%f2
|
||||
fdtox %f2,%f2
|
||||
fxtod %f2,%f2
|
||||
fmuld %f2,%f4,%f2
|
||||
fsubd %f0,%f2,%f0
|
||||
.end
|
||||
|
||||
|
||||
!
|
||||
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
|
||||
! double * /* 0 */,
|
||||
! double * /*result16*/, double * /* result32 */
|
||||
! float * /*source - should be unsigned int*
|
||||
! converted to float* */);
|
||||
!
|
||||
.inline i16_to_d16_and_d32x4,24
|
||||
ldd [%o0],%f2 ! 1/(2^16)
|
||||
ldd [%o1],%f4 ! 2^16
|
||||
ldd [%o2],%f22
|
||||
|
||||
fmovd %f22,%f6
|
||||
ld [%o5],%f7
|
||||
fmovd %f22,%f10
|
||||
ld [%o5+4],%f11
|
||||
fmovd %f22,%f14
|
||||
ld [%o5+8],%f15
|
||||
fmovd %f22,%f18
|
||||
ld [%o5+12],%f19
|
||||
fxtod %f6,%f6
|
||||
std %f6,[%o4]
|
||||
fxtod %f10,%f10
|
||||
std %f10,[%o4+8]
|
||||
fxtod %f14,%f14
|
||||
std %f14,[%o4+16]
|
||||
fxtod %f18,%f18
|
||||
std %f18,[%o4+24]
|
||||
fmuld %f2,%f6,%f8
|
||||
fmuld %f2,%f10,%f12
|
||||
fmuld %f2,%f14,%f16
|
||||
fmuld %f2,%f18,%f20
|
||||
fdtox %f8,%f8
|
||||
fdtox %f12,%f12
|
||||
fdtox %f16,%f16
|
||||
fdtox %f20,%f20
|
||||
fxtod %f8,%f8
|
||||
std %f8,[%o3+8]
|
||||
fxtod %f12,%f12
|
||||
std %f12,[%o3+24]
|
||||
fxtod %f16,%f16
|
||||
std %f16,[%o3+40]
|
||||
fxtod %f20,%f20
|
||||
std %f20,[%o3+56]
|
||||
fmuld %f8,%f4,%f8
|
||||
fmuld %f12,%f4,%f12
|
||||
fmuld %f16,%f4,%f16
|
||||
fmuld %f20,%f4,%f20
|
||||
fsubd %f6,%f8,%f8
|
||||
std %f8,[%o3]
|
||||
fsubd %f10,%f12,%f12
|
||||
std %f12,[%o3+16]
|
||||
fsubd %f14,%f16,%f16
|
||||
std %f16,[%o3+32]
|
||||
fsubd %f18,%f20,%f20
|
||||
std %f20,[%o3+48]
|
||||
.end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* ***** 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 Multi-precision Binary Polynomial Arithmetic Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
* 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 _MP_GF2M_PRIV_H_
|
||||
#define _MP_GF2M_PRIV_H_
|
||||
|
||||
#include "mpi-priv.h"
|
||||
|
||||
extern const mp_digit mp_gf2m_sqr_tb[16];
|
||||
|
||||
#if defined(MP_USE_UINT_DIGIT)
|
||||
#define MP_DIGIT_BITS 32
|
||||
#else
|
||||
#define MP_DIGIT_BITS 64
|
||||
#endif
|
||||
|
||||
/* Platform-specific macros for fast binary polynomial squaring. */
|
||||
#if MP_DIGIT_BITS == 32
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#else
|
||||
#define gf2m_SQR1(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF]
|
||||
#define gf2m_SQR0(w) \
|
||||
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
|
||||
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
|
||||
#endif
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0);
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0);
|
||||
|
||||
#endif /* _MP_GF2M_PRIV_H_ */
|
||||
@@ -1,600 +0,0 @@
|
||||
/*
|
||||
* ***** 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 Multi-precision Binary Polynomial Arithmetic Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
* 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 "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
|
||||
const mp_digit mp_gf2m_sqr_tb[16] =
|
||||
{
|
||||
0, 1, 4, 5, 16, 17, 20, 21,
|
||||
64, 65, 68, 69, 80, 81, 84, 85
|
||||
};
|
||||
|
||||
/* Multiply two binary polynomials mp_digits a, b.
|
||||
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
|
||||
* Output in two mp_digits rh, rl.
|
||||
*/
|
||||
#if MP_DIGIT_BITS == 32
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[8], top2b = a >> 30;
|
||||
register mp_digit a1, a2, a4;
|
||||
|
||||
a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
|
||||
|
||||
tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
|
||||
tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
|
||||
|
||||
s = tab[b & 0x7]; l = s;
|
||||
s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
|
||||
s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
|
||||
s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
|
||||
s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
|
||||
s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
|
||||
s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
|
||||
s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
|
||||
s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
|
||||
s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
|
||||
s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
|
||||
|
||||
/* compensate for the top two bits of a */
|
||||
|
||||
if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
|
||||
if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#else
|
||||
void
|
||||
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
|
||||
{
|
||||
register mp_digit h, l, s;
|
||||
mp_digit tab[16], top3b = a >> 61;
|
||||
register mp_digit a1, a2, a4, a8;
|
||||
|
||||
a1 = a & (0x1FFFFFFFFFFFFFFF); a2 = a1 << 1;
|
||||
a4 = a2 << 1; a8 = a4 << 1;
|
||||
tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
|
||||
tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
|
||||
tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
|
||||
tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
|
||||
|
||||
s = tab[b & 0xF]; l = s;
|
||||
s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
|
||||
s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
|
||||
s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
|
||||
s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
|
||||
s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
|
||||
s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
|
||||
s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
|
||||
s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
|
||||
s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
|
||||
s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
|
||||
s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
|
||||
s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
|
||||
s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
|
||||
s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
|
||||
s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
|
||||
|
||||
/* compensate for the top three bits of a */
|
||||
|
||||
if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
|
||||
if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
|
||||
if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
|
||||
|
||||
*rh = h; *rl = l;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
|
||||
* result is a binary polynomial in 4 mp_digits r[4].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit m1, m0;
|
||||
/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
|
||||
s_bmul_1x1(r+3, r+2, a1, b1);
|
||||
s_bmul_1x1(r+1, r, a0, b0);
|
||||
s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
|
||||
/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
|
||||
r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
|
||||
r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
|
||||
* result is a binary polynomial in 6 mp_digits r[6].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void
|
||||
s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
|
||||
const mp_digit b2, const mp_digit b1, const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_1x1(r+5, r+4, a2, b2); /* fill top 2 words */
|
||||
s_bmul_2x2(zm, a1, a2^a0, b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3];
|
||||
zm[2] ^= r[2];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
|
||||
* result is a binary polynomial in 8 mp_digits r[8].
|
||||
* The caller MUST ensure that r has the right amount of space allocated.
|
||||
*/
|
||||
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
|
||||
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
|
||||
const mp_digit b0)
|
||||
{
|
||||
mp_digit zm[4];
|
||||
|
||||
s_bmul_2x2(r+4, a3, a2, b3, b2); /* fill top 4 words */
|
||||
s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */
|
||||
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
|
||||
|
||||
zm[3] ^= r[3] ^ r[7];
|
||||
zm[2] ^= r[2] ^ r[6];
|
||||
zm[1] ^= r[1] ^ r[5];
|
||||
zm[0] ^= r[0] ^ r[4];
|
||||
|
||||
r[5] ^= zm[3];
|
||||
r[4] ^= zm[2];
|
||||
r[3] ^= zm[1];
|
||||
r[2] ^= zm[0];
|
||||
}
|
||||
|
||||
/* Compute addition of two binary polynomials a and b,
|
||||
* store result in c; c could be a or b, a and b could be equal;
|
||||
* c is the bitwise XOR of a and b.
|
||||
*/
|
||||
mp_err
|
||||
mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pa, *pb, *pc;
|
||||
mp_size ix;
|
||||
mp_size used_pa, used_pb;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* Add all digits up to the precision of b. If b had more
|
||||
* precision than a initially, swap a, b first
|
||||
*/
|
||||
if (MP_USED(a) >= MP_USED(b)) {
|
||||
pa = MP_DIGITS(a);
|
||||
pb = MP_DIGITS(b);
|
||||
used_pa = MP_USED(a);
|
||||
used_pb = MP_USED(b);
|
||||
} else {
|
||||
pa = MP_DIGITS(b);
|
||||
pb = MP_DIGITS(a);
|
||||
used_pa = MP_USED(b);
|
||||
used_pb = MP_USED(a);
|
||||
}
|
||||
|
||||
/* Make sure c has enough precision for the output value */
|
||||
MP_CHECKOK( s_mp_pad(c, used_pa) );
|
||||
|
||||
/* Do word-by-word xor */
|
||||
pc = MP_DIGITS(c);
|
||||
for (ix = 0; ix < used_pb; ix++) {
|
||||
(*pc++) = (*pa++) ^ (*pb++);
|
||||
}
|
||||
|
||||
/* Finish the rest of digits until we're actually done */
|
||||
for (; ix < used_pa; ++ix) {
|
||||
*pc++ = *pa++;
|
||||
}
|
||||
|
||||
MP_USED(c) = used_pa;
|
||||
MP_SIGN(c) = ZPOS;
|
||||
s_mp_clamp(c);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#define s_mp_div2(a) MP_CHECKOK( mpl_rsh((a), (a), 1) );
|
||||
|
||||
/* Compute binary polynomial multiply d = a * b */
|
||||
static void
|
||||
s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ = a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d = carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply accumulate d ^= a * b */
|
||||
static void
|
||||
s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
|
||||
{
|
||||
mp_digit a_i, a0b0, a1b1, carry = 0;
|
||||
while (a_len--) {
|
||||
a_i = *a++;
|
||||
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
|
||||
*d++ ^= a0b0 ^ carry;
|
||||
carry = a1b1;
|
||||
}
|
||||
*d ^= carry;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial xor multiply c = a * b.
|
||||
* All parameters may be identical.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_digit *pb, b_i;
|
||||
mp_int tmp;
|
||||
mp_size ib, a_used, b_used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (a == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
if (a == b)
|
||||
b = &tmp;
|
||||
a = &tmp;
|
||||
} else if (b == c) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, b) );
|
||||
b = &tmp;
|
||||
}
|
||||
|
||||
if (MP_USED(a) < MP_USED(b)) {
|
||||
const mp_int *xch = b; /* switch a and b if b longer */
|
||||
b = a;
|
||||
a = xch;
|
||||
}
|
||||
|
||||
MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(c, USED(a) + USED(b)) );
|
||||
|
||||
pb = MP_DIGITS(b);
|
||||
s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
|
||||
|
||||
/* Outer loop: Digits of b */
|
||||
a_used = MP_USED(a);
|
||||
b_used = MP_USED(b);
|
||||
MP_USED(c) = a_used + b_used;
|
||||
for (ib = 1; ib < b_used; ib++) {
|
||||
b_i = *pb++;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
if (b_i)
|
||||
s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
|
||||
else
|
||||
MP_DIGIT(c, ib + a_used) = b_i;
|
||||
}
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
SIGN(c) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Compute modular reduction of a and store result in r.
|
||||
* r could be a.
|
||||
* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
int j, k;
|
||||
int n, dN, d0, d1;
|
||||
mp_digit zz, *z, tmp;
|
||||
mp_size used;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* The algorithm does the reduction in place in r,
|
||||
* if a != r, copy a into r first so reduction can be done in r
|
||||
*/
|
||||
if (a != r) {
|
||||
MP_CHECKOK( mp_copy(a, r) );
|
||||
}
|
||||
z = MP_DIGITS(r);
|
||||
|
||||
/* start reduction */
|
||||
dN = p[0] / MP_DIGIT_BITS;
|
||||
used = MP_USED(r);
|
||||
|
||||
for (j = used - 1; j > dN;) {
|
||||
|
||||
zz = z[j];
|
||||
if (zz == 0) {
|
||||
j--; continue;
|
||||
}
|
||||
z[j] = 0;
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k] */
|
||||
n = p[0] - p[k];
|
||||
d0 = n % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
n /= MP_DIGIT_BITS;
|
||||
z[j-n] ^= (zz>>d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz<<d1);
|
||||
}
|
||||
|
||||
/* reducing component t^0 */
|
||||
n = dN;
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[j-n] ^= (zz >> d0);
|
||||
if (d0)
|
||||
z[j-n-1] ^= (zz << d1);
|
||||
|
||||
}
|
||||
|
||||
/* final round of reduction */
|
||||
while (j == dN) {
|
||||
|
||||
d0 = p[0] % MP_DIGIT_BITS;
|
||||
zz = z[dN] >> d0;
|
||||
if (zz == 0) break;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
|
||||
/* clear up the top d1 bits */
|
||||
if (d0) z[dN] = (z[dN] << d1) >> d1;
|
||||
*z ^= zz; /* reduction t^0 component */
|
||||
|
||||
for (k = 1; p[k] > 0; k++) {
|
||||
/* reducing component t^p[k]*/
|
||||
n = p[k] / MP_DIGIT_BITS;
|
||||
d0 = p[k] % MP_DIGIT_BITS;
|
||||
d1 = MP_DIGIT_BITS - d0;
|
||||
z[n] ^= (zz << d0);
|
||||
tmp = zz >> d1;
|
||||
if (d0 && tmp)
|
||||
z[n+1] ^= tmp;
|
||||
}
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p,
|
||||
* Store the result in r. r could be a or b; a could be b.
|
||||
*/
|
||||
mp_err
|
||||
mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
if (a == b) return mp_bsqrmod(a, p, r);
|
||||
if ((res = mp_bmul(a, b, r) ) != MP_OKAY)
|
||||
return res;
|
||||
return mp_bmod(r, p, r);
|
||||
}
|
||||
|
||||
/* Compute binary polynomial squaring c = a*a mod p .
|
||||
* Parameter r and a can be identical.
|
||||
*/
|
||||
|
||||
mp_err
|
||||
mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_digit *pa, *pr, a_i;
|
||||
mp_int tmp;
|
||||
mp_size ia, a_used;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && r != NULL, MP_BADARG);
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
if (a == r) {
|
||||
MP_CHECKOK( mp_init_copy(&tmp, a) );
|
||||
a = &tmp;
|
||||
}
|
||||
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
MP_CHECKOK( s_mp_pad(r, 2*USED(a)) );
|
||||
|
||||
pa = MP_DIGITS(a);
|
||||
pr = MP_DIGITS(r);
|
||||
a_used = MP_USED(a);
|
||||
MP_USED(r) = 2 * a_used;
|
||||
|
||||
for (ia = 0; ia < a_used; ia++) {
|
||||
a_i = *pa++;
|
||||
*pr++ = gf2m_SQR0(a_i);
|
||||
*pr++ = gf2m_SQR1(a_i);
|
||||
}
|
||||
|
||||
MP_CHECKOK( mp_bmod(r, p, r) );
|
||||
s_mp_clamp(r);
|
||||
SIGN(r) = ZPOS;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
|
||||
* Store the result in r. r could be x or y, and x could equal y.
|
||||
* Uses algorithm Modular_Division_GF(2^m) from
|
||||
* Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to
|
||||
* the Great Divide".
|
||||
*/
|
||||
int
|
||||
mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r)
|
||||
{
|
||||
mp_int aa, bb, uu;
|
||||
mp_int *a, *b, *u, *v;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_DIGITS(&aa) = 0;
|
||||
MP_DIGITS(&bb) = 0;
|
||||
MP_DIGITS(&uu) = 0;
|
||||
|
||||
MP_CHECKOK( mp_init_copy(&aa, x) );
|
||||
MP_CHECKOK( mp_init_copy(&uu, y) );
|
||||
MP_CHECKOK( mp_init_copy(&bb, pp) );
|
||||
MP_CHECKOK( s_mp_pad(r, USED(pp)) );
|
||||
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
|
||||
|
||||
a = &aa; b= &bb; u=&uu; v=r;
|
||||
/* reduce x and y mod p */
|
||||
MP_CHECKOK( mp_bmod(a, p, a) );
|
||||
MP_CHECKOK( mp_bmod(u, p, u) );
|
||||
|
||||
while (!mp_isodd(a)) {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
}
|
||||
|
||||
do {
|
||||
if (mp_cmp_mag(b, a) > 0) {
|
||||
MP_CHECKOK( mp_badd(b, a, b) );
|
||||
MP_CHECKOK( mp_badd(v, u, v) );
|
||||
do {
|
||||
s_mp_div2(b);
|
||||
if (mp_isodd(v)) {
|
||||
MP_CHECKOK( mp_badd(v, pp, v) );
|
||||
}
|
||||
s_mp_div2(v);
|
||||
} while (!mp_isodd(b));
|
||||
}
|
||||
else if ((MP_DIGIT(a,0) == 1) && (MP_USED(a) == 1))
|
||||
break;
|
||||
else {
|
||||
MP_CHECKOK( mp_badd(a, b, a) );
|
||||
MP_CHECKOK( mp_badd(u, v, u) );
|
||||
do {
|
||||
s_mp_div2(a);
|
||||
if (mp_isodd(u)) {
|
||||
MP_CHECKOK( mp_badd(u, pp, u) );
|
||||
}
|
||||
s_mp_div2(u);
|
||||
} while (!mp_isodd(a));
|
||||
}
|
||||
} while (1);
|
||||
|
||||
MP_CHECKOK( mp_copy(u, r) );
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/* Convert the bit-string representation of a polynomial a into an array
|
||||
* of integers corresponding to the bits with non-zero coefficient.
|
||||
* Up to max elements of the array will be filled. Return value is total
|
||||
* number of coefficients that would be extracted if array was large enough.
|
||||
*/
|
||||
int
|
||||
mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
|
||||
{
|
||||
int i, j, k;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
|
||||
for (k = 0; k < max; k++) p[k] = 0;
|
||||
k = 0;
|
||||
|
||||
for (i = MP_USED(a) - 1; i >= 0; i--) {
|
||||
mask = top_bit;
|
||||
for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
|
||||
if (MP_DIGITS(a)[i] & mask) {
|
||||
if (k < max) p[k] = MP_DIGIT_BIT * i + j;
|
||||
k++;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Convert the coefficient array representation of a polynomial to a
|
||||
* bit-string. The array must be terminated by 0.
|
||||
*/
|
||||
mp_err
|
||||
mp_barr2poly(const unsigned int p[], mp_int *a)
|
||||
{
|
||||
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
|
||||
mp_zero(a);
|
||||
for (i = 0; p[i] > 0; i++) {
|
||||
MP_CHECKOK( mpl_set_bit(a, p[i], 1) );
|
||||
}
|
||||
MP_CHECKOK( mpl_set_bit(a, 0, 1) );
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* ***** 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 Multi-precision Binary Polynomial Arithmetic Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca> of Sun Laboratories.
|
||||
*
|
||||
* 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 _MP_GF2M_H_
|
||||
#define _MP_GF2M_H_
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_bmul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
|
||||
/* For modular arithmetic, the irreducible polynomial f(t) is represented
|
||||
* as an array of int[], where f(t) is of the form:
|
||||
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
|
||||
* where m = p[0] > p[1] > ... > p[k] = 0.
|
||||
*/
|
||||
mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[],
|
||||
mp_int *r);
|
||||
mp_err mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r);
|
||||
mp_err mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
|
||||
const unsigned int p[], mp_int *r);
|
||||
|
||||
int mp_bpoly2arr(const mp_int *a, unsigned int p[], int max);
|
||||
mp_err mp_barr2poly(const unsigned int p[], mp_int *a);
|
||||
|
||||
#endif /* _MP_GF2M_H_ */
|
||||
@@ -1,760 +0,0 @@
|
||||
/* ***** 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Red Hat, Inc
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert Relyea <rrelyea@redhat.com>
|
||||
*
|
||||
* 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 "mpi.h"
|
||||
|
||||
/*
|
||||
* This file implements a single function: mpi_getProcessorLineSize();
|
||||
* mpi_getProcessorLineSize() returns the size in bytes of the cache line
|
||||
* if a cache exists, or zero if there is no cache. If more than one
|
||||
* cache line exists, it should return the smallest line size (which is
|
||||
* usually the L1 cache).
|
||||
*
|
||||
* mp_modexp uses this information to make sure that private key information
|
||||
* isn't being leaked through the cache.
|
||||
*
|
||||
* Currently the file returns good data for most modern x86 processors, and
|
||||
* reasonable data on 64-bit ppc processors. All other processors are assumed
|
||||
* to have a cache line size of 32 bytes unless modified by target.mk.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(i386) || defined(__i386) || defined(__X86__) || defined (_M_IX86)
|
||||
/* X86 processors have special instructions that tell us about the cache */
|
||||
#include "string.h"
|
||||
|
||||
/* Generic CPUID function */
|
||||
#ifndef _WIN32
|
||||
static void cpuid(unsigned long op, unsigned long *eax,
|
||||
unsigned long *ebx, unsigned long *ecx,
|
||||
unsigned long *edx)
|
||||
{
|
||||
/* sigh GCC isn't smart enough to save the ebx PIC register on it's own
|
||||
* in this case, so do it by hand. */
|
||||
__asm__("pushl %%ebx\n\t"
|
||||
"cpuid\n\t"
|
||||
"mov %%ebx,%1\n\t"
|
||||
"popl %%ebx\n\t"
|
||||
: "=a" (*eax),
|
||||
"=r" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (op));
|
||||
}
|
||||
|
||||
/*
|
||||
* try flipping a processor flag to determine CPU type
|
||||
*/
|
||||
static unsigned long changeFlag(unsigned long flag)
|
||||
{
|
||||
unsigned long changedFlags, originalFlags;
|
||||
__asm__("pushfl\n\t" /* get the flags */
|
||||
"popl %0\n\t"
|
||||
"movl %0,%1\n\t" /* save the original flags */
|
||||
"xor %0,%2\n\t" /* flip the but */
|
||||
"pushl %0\n\t" /* set the flags */
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t" /* get the flags again (for return) */
|
||||
"popl %0\n\t"
|
||||
"pushl %1\n\t" /* restore the original flags */
|
||||
"popfl\n\t"
|
||||
: "=r" (changedFlags),
|
||||
"=r" (originalFlags)
|
||||
: "r" (flag));
|
||||
return changedFlags ^ originalFlags;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* windows versions of the above assembler
|
||||
*/
|
||||
#define wcpuid __asm __emit 0fh __asm __emit 0a2h
|
||||
static void cpuid(unsigned long op, unsigned long *Reax, unsigned long *Rebx,
|
||||
unsigned long *Recx, unsigned long *Redx)
|
||||
{
|
||||
unsigned long Leax, Lebx, Lecx, Ledx;
|
||||
__asm {
|
||||
pushad
|
||||
mov eax,op
|
||||
wcpuid
|
||||
mov Leax,eax
|
||||
mov Lebx,ebx
|
||||
mov Lecx,ecx
|
||||
mov Ledx,edx
|
||||
popad
|
||||
}
|
||||
*Reax = Leax;
|
||||
*Rebx = Lebx;
|
||||
*Recx = Lecx;
|
||||
*Redx = Ledx;
|
||||
}
|
||||
|
||||
static unsigned long changeFlag(unsigned long flag)
|
||||
{
|
||||
unsigned long changedFlags, originalFlags;
|
||||
__asm {
|
||||
pushad
|
||||
pushfd /* get the flags */
|
||||
pop eax
|
||||
mov ecx,eax /* save the original flags */
|
||||
mov originalFlags,ecx /* save the original flags */
|
||||
mov ebx,flag
|
||||
xor eax,ebx /* flip the but */
|
||||
push eax /* set the flags */
|
||||
popfd
|
||||
pushfd /* get the flags again (for return) */
|
||||
pop eax
|
||||
push ecx /* restore the original flags */
|
||||
popfd
|
||||
mov changedFlags,eax
|
||||
popad
|
||||
}
|
||||
return changedFlags ^ originalFlags;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define AC_FLAG 0x40000
|
||||
#define ID_FLAG 0x200000
|
||||
|
||||
/* 386 processors can't flip the AC_FLAG, intel AP Note AP-485 */
|
||||
static int is386()
|
||||
{
|
||||
return changeFlag(AC_FLAG) == 0;
|
||||
}
|
||||
|
||||
/* 486 processors can't flip the ID_FLAG, intel AP Note AP-485 */
|
||||
static int is486()
|
||||
{
|
||||
return changeFlag(ID_FLAG) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* table for Intel Cache.
|
||||
* See Intel Application Note AP-485 for more information
|
||||
*/
|
||||
typedef enum {
|
||||
Cache_NONE = 0,
|
||||
Cache_UNKNOWN = 1,
|
||||
Cache_TLB = 2,
|
||||
Cache_Trace = 3,
|
||||
Cache_L1 = 4,
|
||||
Cache_L2 = 5 ,
|
||||
Cache_L3 = 6
|
||||
} CacheType;
|
||||
|
||||
#define DATA_INSTR 1
|
||||
#define DATA_DATA 2
|
||||
#define DATA_BOTH 3
|
||||
#define DATA_TRACE 4
|
||||
#define DATA_NONE 0
|
||||
|
||||
#define TLB_4k 0x01
|
||||
#define TLB_2M 0x08
|
||||
#define TLB_4M 0x10
|
||||
#define TLB_4Mk 0x11
|
||||
#define TLB_ALL 0x19
|
||||
|
||||
#define k * 1024
|
||||
#define M * (1024*1024)
|
||||
#define G * (1024*1024*1024)
|
||||
|
||||
struct _cache {
|
||||
CacheType type;
|
||||
unsigned long data;
|
||||
#define pageSize size
|
||||
#define trcuops size
|
||||
unsigned long size;
|
||||
unsigned long association;
|
||||
#define tlbEntries lineSize
|
||||
unsigned long lineSize;
|
||||
} CacheMap[] = {
|
||||
/* 00 */ {Cache_NONE, DATA_NONE, 0, 0, 0 },
|
||||
/* 01 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 32 },
|
||||
/* 02 */ {Cache_TLB, DATA_INSTR, TLB_4M, 0, 2 },
|
||||
/* 03 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 64 },
|
||||
/* 04 */ {Cache_TLB, DATA_DATA, TLB_4M, 4, 8 },
|
||||
/* 05 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 06 */ {Cache_L1, DATA_INSTR, 8 k, 4, 32 },
|
||||
/* 07 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 08 */ {Cache_L1, DATA_INSTR, 16 k, 4, 32 },
|
||||
/* 09 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0a */ {Cache_L1, DATA_DATA, 8 k, 4, 32 },
|
||||
/* 0b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0c */ {Cache_L1, DATA_DATA, 16 k, 4, 32 },
|
||||
/* 0d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 0f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 10 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 11 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 12 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 13 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 14 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 15 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 16 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 17 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 18 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 19 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 1f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 20 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 21 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 22 */ {Cache_L3, DATA_BOTH, 512 k, 8, 64 },
|
||||
/* 23 */ {Cache_L3, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 24 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 25 */ {Cache_L3, DATA_BOTH, 2 M, 8, 64 },
|
||||
/* 26 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 27 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 28 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 29 */ {Cache_L3, DATA_BOTH, 4 M, 8, 64 },
|
||||
/* 2a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2c */ {Cache_L1, DATA_DATA, 32 k, 8, 64 },
|
||||
/* 2d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 2f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 30 */ {Cache_L1, DATA_INSTR, 32 k, 8, 64 },
|
||||
/* 31 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 32 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 33 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 34 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 35 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 36 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 37 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 38 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 39 */ {Cache_L2, DATA_BOTH, 128 k, 4, 64 },
|
||||
/* 3a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3b */ {Cache_L2, DATA_BOTH, 128 k, 2, 64 },
|
||||
/* 3c */ {Cache_L2, DATA_BOTH, 256 k, 4, 64 },
|
||||
/* 3d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 3f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 40 */ {Cache_L2, DATA_NONE, 0, 0, 0 },
|
||||
/* 41 */ {Cache_L2, DATA_BOTH, 128 k, 4, 32 },
|
||||
/* 42 */ {Cache_L2, DATA_BOTH, 256 k, 4, 32 },
|
||||
/* 43 */ {Cache_L2, DATA_BOTH, 512 k, 4, 32 },
|
||||
/* 44 */ {Cache_L2, DATA_BOTH, 1 M, 4, 32 },
|
||||
/* 45 */ {Cache_L2, DATA_BOTH, 2 M, 4, 32 },
|
||||
/* 46 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 47 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 48 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 49 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 4f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 50 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 64 },
|
||||
/* 51 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 128 },
|
||||
/* 52 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 256 },
|
||||
/* 53 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 54 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 55 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 56 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 57 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 58 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 59 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5b */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 64 },
|
||||
/* 5c */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 128 },
|
||||
/* 5d */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 256 },
|
||||
/* 5e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 5f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 60 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 61 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 62 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 63 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 64 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 65 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 66 */ {Cache_L1, DATA_DATA, 8 k, 4, 64 },
|
||||
/* 67 */ {Cache_L1, DATA_DATA, 16 k, 4, 64 },
|
||||
/* 68 */ {Cache_L1, DATA_DATA, 32 k, 4, 64 },
|
||||
/* 69 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 6f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 70 */ {Cache_Trace, DATA_TRACE, 12 k, 8, 1 },
|
||||
/* 71 */ {Cache_Trace, DATA_TRACE, 16 k, 8, 1 },
|
||||
/* 72 */ {Cache_Trace, DATA_TRACE, 32 k, 8, 1 },
|
||||
/* 73 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 74 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 75 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 76 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 77 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 78 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 79 */ {Cache_L2, DATA_BOTH, 128 k, 8, 64 },
|
||||
/* 7a */ {Cache_L2, DATA_BOTH, 256 k, 8, 64 },
|
||||
/* 7b */ {Cache_L2, DATA_BOTH, 512 k, 8, 64 },
|
||||
/* 7c */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 7d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 7e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 7f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 80 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 81 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 82 */ {Cache_L2, DATA_BOTH, 256 k, 8, 32 },
|
||||
/* 83 */ {Cache_L2, DATA_BOTH, 512 k, 8, 32 },
|
||||
/* 84 */ {Cache_L2, DATA_BOTH, 1 M, 8, 32 },
|
||||
/* 85 */ {Cache_L2, DATA_BOTH, 2 M, 8, 32 },
|
||||
/* 86 */ {Cache_L2, DATA_BOTH, 512 k, 4, 64 },
|
||||
/* 87 */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
|
||||
/* 88 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 89 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 8f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 90 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 91 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 92 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 93 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 94 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 95 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 96 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 97 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 98 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 99 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* 9f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* a9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* aa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ab */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ac */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ad */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ae */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* af */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b0 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 128 },
|
||||
/* b1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b3 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 128 },
|
||||
/* b4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* b9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ba */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* be */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* bf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* c9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ca */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ce */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* cf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* d9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* da */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* db */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* dc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* dd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* de */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* df */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* e9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ea */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* eb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ec */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ed */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ee */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ef */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* f9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* fe */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
|
||||
/* ff */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* use the above table to determine the CacheEntryLineSize.
|
||||
*/
|
||||
static void
|
||||
getIntelCacheEntryLineSize(unsigned long val, int *level,
|
||||
unsigned long *lineSize)
|
||||
{
|
||||
CacheType type;
|
||||
|
||||
type = CacheMap[val].type;
|
||||
/* only interested in data caches */
|
||||
/* NOTE val = 0x40 is a special value that means no L2 or L3 cache.
|
||||
* this data check has the side effect of rejecting that entry. If
|
||||
* that wasn't the case, we could have to reject it explicitly */
|
||||
if ((CacheMap[val].data & DATA_DATA) != DATA_DATA) {
|
||||
return;
|
||||
}
|
||||
/* look at the caches, skip types we aren't interested in.
|
||||
* if we already have a value for a lower level cache, skip the
|
||||
* current entry */
|
||||
if (type == Cache_L1) {
|
||||
*level = 1;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
} else if ((*level >= 2) && type == Cache_L2) {
|
||||
*level = 2;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
} else if ((*level >= 3) && type == Cache_L3) {
|
||||
*level = 3;
|
||||
*lineSize = CacheMap[val].lineSize;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
getIntelRegisterCacheLineSize(unsigned long val,
|
||||
int *level, unsigned long *lineSize)
|
||||
{
|
||||
getIntelCacheEntryLineSize(val >> 24 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val >> 16 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val >> 8 & 0xff, level, lineSize);
|
||||
getIntelCacheEntryLineSize(val & 0xff, level, lineSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns '0' if no recognized cache is found, or if the cache
|
||||
* information is supported by this processor
|
||||
*/
|
||||
static unsigned long
|
||||
getIntelCacheLineSize(int cpuidLevel)
|
||||
{
|
||||
int level = 4;
|
||||
unsigned long lineSize = 0;
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
int repeat, count;
|
||||
|
||||
if (cpuidLevel < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* command '2' of the cpuid is intel's cache info call. Each byte of the
|
||||
* 4 registers contain a potential descriptor for the cache. The CacheMap
|
||||
* table maps the cache entry with the processor cache. Register 'al'
|
||||
* contains a count value that cpuid '2' needs to be called in order to
|
||||
* find all the cache descriptors. Only registers with the high bit set
|
||||
* to 'zero' have valid descriptors. This code loops through all the
|
||||
* required calls to cpuid '2' and passes any valid descriptors it finds
|
||||
* to the getIntelRegisterCacheLineSize code, which breaks the registers
|
||||
* down into their component descriptors. In the end the lineSize of the
|
||||
* lowest level cache data cache is returned. */
|
||||
cpuid(2, &eax, &ebx, &ecx, &edx);
|
||||
repeat = eax & 0xf;
|
||||
for (count = 0; count < repeat; count++) {
|
||||
if ((eax & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(eax & 0xffffff00, &level, &lineSize);
|
||||
}
|
||||
if ((ebx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(ebx, &level, &lineSize);
|
||||
}
|
||||
if ((ecx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(ecx, &level, &lineSize);
|
||||
}
|
||||
if ((edx & 0x80000000) == 0) {
|
||||
getIntelRegisterCacheLineSize(edx, &level, &lineSize);
|
||||
}
|
||||
if (count+1 != repeat) {
|
||||
cpuid(2, &eax, &ebx, &ecx, &edx);
|
||||
}
|
||||
}
|
||||
return lineSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns '0' if the cache info is not supported by this processor.
|
||||
* This is based on the AMD extended cache commands for cpuid.
|
||||
* (see "AMD Processor Recognition Application Note" Publication 20734).
|
||||
* Some other processors use the identical scheme.
|
||||
* (see "Processor Recognition, Transmeta Corporation").
|
||||
*/
|
||||
static unsigned long
|
||||
getOtherCacheLineSize(unsigned long cpuidLevel)
|
||||
{
|
||||
unsigned long lineSize = 0;
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
|
||||
/* get the Extended CPUID level */
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
cpuidLevel = eax;
|
||||
|
||||
if (cpuidLevel >= 0x80000005) {
|
||||
cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
|
||||
lineSize = ecx & 0xff; /* line Size, L1 Data Cache */
|
||||
}
|
||||
return lineSize;
|
||||
}
|
||||
|
||||
char *manMap[] = {
|
||||
#define INTEL 0
|
||||
"GenuineIntel",
|
||||
#define AMD 1
|
||||
"AuthenticAMD",
|
||||
#define CYRIX 2
|
||||
"CyrixInstead",
|
||||
#define CENTAUR 2
|
||||
"CentaurHauls",
|
||||
#define NEXGEN 3
|
||||
"NexGenDriven",
|
||||
#define TRANSMETA 4
|
||||
"GenuineTMx86",
|
||||
#define RISE 5
|
||||
"RiseRiseRise",
|
||||
#define UMC 6
|
||||
"UMC UMC UMC ",
|
||||
#define SIS 7
|
||||
"Sis Sis Sis ",
|
||||
#define NATIONAL 8
|
||||
"Geode by NSC",
|
||||
};
|
||||
|
||||
int n_manufacturers = sizeof(manMap)/sizeof(manMap[0]);
|
||||
|
||||
#define MAN_UNKNOWN 9
|
||||
|
||||
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
unsigned long cpuidLevel;
|
||||
unsigned long cacheLineSize = 0;
|
||||
int manufacturer = MAN_UNKNOWN;
|
||||
int i;
|
||||
char string[65];
|
||||
|
||||
if (is386()) {
|
||||
return 0; /* 386 had no cache */
|
||||
} if (is486()) {
|
||||
return 32; /* really? need more info */
|
||||
}
|
||||
|
||||
/* Pentium, cpuid command is available */
|
||||
cpuid(0, &eax, &ebx, &ecx, &edx);
|
||||
cpuidLevel = eax;
|
||||
*(int *)string = ebx;
|
||||
*(int *)&string[4] = edx;
|
||||
*(int *)&string[8] = ecx;
|
||||
string[12] = 0;
|
||||
|
||||
manufacturer = MAN_UNKNOWN;
|
||||
for (i=0; i < n_manufacturers; i++) {
|
||||
if ( strcmp(manMap[i],string) == 0) {
|
||||
manufacturer = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (manufacturer == INTEL) {
|
||||
cacheLineSize = getIntelCacheLineSize(cpuidLevel);
|
||||
} else {
|
||||
cacheLineSize = getOtherCacheLineSize(cpuidLevel);
|
||||
}
|
||||
/* doesn't support cache info based on cpuid. This means
|
||||
* an old pentium class processor, which have cache lines of
|
||||
* 32. If we learn differently, we can use a switch based on
|
||||
* the Manufacturer id */
|
||||
if (cacheLineSize == 0) {
|
||||
cacheLineSize = 32;
|
||||
}
|
||||
return cacheLineSize;
|
||||
}
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
#if defined(__ppc64__)
|
||||
/*
|
||||
* Sigh, The PPC has some really nice features to help us determine cache
|
||||
* size, since it had lots of direct control functions to do so. The POWER
|
||||
* processor even has an instruction to do this, but it was dropped in
|
||||
* PowerPC. Unfortunately most of them are not available in user mode.
|
||||
*
|
||||
* The dcbz function would be a great way to determine cache line size except
|
||||
* 1) it only works on write-back memory (it throws an exception otherwise),
|
||||
* and 2) because so many mac programs 'knew' the processor cache size was
|
||||
* 32 bytes, they used this instruction as a fast 'zero 32 bytes'. Now the new
|
||||
* G5 processor has 128 byte cache, but dcbz only clears 32 bytes to keep
|
||||
* these programs happy. dcbzl work if 64 bit instructions are supported.
|
||||
* If you know 64 bit instructions are supported, and that stack is
|
||||
* write-back, you can use this code.
|
||||
*/
|
||||
#include "memory.h"
|
||||
|
||||
/* clear the cache line that contains 'array' */
|
||||
static inline void dcbzl(char *array)
|
||||
{
|
||||
register char *a asm("r2") = array;
|
||||
__asm__ __volatile__( "dcbzl %0,r0" : "=r" (a): "0"(a) );
|
||||
}
|
||||
|
||||
|
||||
#define PPC_DO_ALIGN(x,y) ((char *)\
|
||||
((((long long) (x))+((y)-1))&~((y)-1)))
|
||||
|
||||
#define PPC_MAX_LINE_SIZE 256
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
char testArray[2*PPC_MAX_LINE_SIZE+1];
|
||||
char *test;
|
||||
int i;
|
||||
|
||||
/* align the array on a maximum line size boundary, so we
|
||||
* know we are starting to clear from the first address */
|
||||
test = PPC_DO_ALIGN(testArray, PPC_MAX_LINE_SIZE);
|
||||
/* set all the values to 1's */
|
||||
memset(test, 0xff, PPC_MAX_LINE_SIZE);
|
||||
/* clear one cache block starting at 'test' */
|
||||
dcbzl(test);
|
||||
|
||||
/* find the size of the cleared area, that's our block size */
|
||||
for (i=PPC_MAX_LINE_SIZE; i != 0; i = i/2) {
|
||||
if (test[i-1] == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* put other processor and platform specific cache code here
|
||||
* return the smallest cache line size in bytes on the processor
|
||||
* (usually the L1 cache). If the OS has a call, this would be
|
||||
* a greate place to put it.
|
||||
*
|
||||
* If there is no cache, return 0;
|
||||
*
|
||||
* define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED so the generic functions
|
||||
* below aren't compiled.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* target.mk can define LINE_SIZE if it's common for the family or OS */
|
||||
#if defined(LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINED)
|
||||
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
return LINE_SIZE;
|
||||
}
|
||||
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
|
||||
#endif
|
||||
|
||||
|
||||
/* If no way to get the processor cache line size has been defined, assume
|
||||
* it's 32 bytes (most common value, does not significantly impact performance
|
||||
*/
|
||||
#ifndef MPI_GET_PROCESSER_LINE_SIZE_DEFINED
|
||||
unsigned long
|
||||
mpi_getProcessorLineSize()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_IT
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
printf("line size = %d\n", mpi_getProcessorLineSize());
|
||||
}
|
||||
#endif
|
||||
@@ -1,112 +0,0 @@
|
||||
/* Default configuration for MPI library
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1997
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: mpi-config.h,v 1.5 2004-04-25 15:03:10 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifndef MPI_CONFIG_H_
|
||||
#define MPI_CONFIG_H_
|
||||
|
||||
/*
|
||||
For boolean options,
|
||||
0 = no
|
||||
1 = yes
|
||||
|
||||
Other options are documented individually.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MP_IOFUNC
|
||||
#define MP_IOFUNC 0 /* include mp_print() ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MODARITH
|
||||
#define MP_MODARITH 1 /* include modular arithmetic ? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_NUMTH
|
||||
#define MP_NUMTH 1 /* include number theoretic functions? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_LOGTAB
|
||||
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMSET
|
||||
#define MP_MEMSET 1 /* use memset() to zero buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MEMCPY
|
||||
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_CRYPTO
|
||||
#define MP_CRYPTO 1 /* erase memory on free? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_ARGCHK
|
||||
/*
|
||||
0 = no parameter checks
|
||||
1 = runtime checks, continue execution and return an error to caller
|
||||
2 = assertions; dump core on parameter errors
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define MP_ARGCHK 2 /* how to check input arguments */
|
||||
#else
|
||||
#define MP_ARGCHK 1 /* how to check input arguments */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEBUG
|
||||
#define MP_DEBUG 0 /* print diagnostic output? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_DEFPREC
|
||||
#define MP_DEFPREC 64 /* default precision, in digits */
|
||||
#endif
|
||||
|
||||
#ifndef MP_MACRO
|
||||
#define MP_MACRO 0 /* use macros for frequent calls? */
|
||||
#endif
|
||||
|
||||
#ifndef MP_SQUARE
|
||||
#define MP_SQUARE 1 /* use separate squaring code? */
|
||||
#endif
|
||||
|
||||
#endif /* ifndef MPI_CONFIG_H_ */
|
||||
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
/*
|
||||
* mpi-priv.h - Private header file for MPI
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* NOTE WELL: the content of this header file is NOT part of the "public"
|
||||
* API for the MPI library, and may change at any time.
|
||||
* Application programs that use libmpi should NOT include this header file.
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: mpi-priv.h,v 1.18 2005-02-25 04:30:11 julien.pierre.bugs%sun.com Exp $ */
|
||||
#ifndef _MPI_PRIV_H_
|
||||
#define _MPI_PRIV_H_ 1
|
||||
|
||||
#include "mpi.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if MP_DEBUG
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
|
||||
#else
|
||||
#define DIAG(T,V)
|
||||
#endif
|
||||
|
||||
/* If we aren't using a wired-in logarithm table, we need to include
|
||||
the math library to get the log() function
|
||||
*/
|
||||
|
||||
/* {{{ s_logv_2[] - log table for 2 in various bases */
|
||||
|
||||
#if MP_LOGTAB
|
||||
/*
|
||||
A table of the logs of 2 for various bases (the 0 and 1 entries of
|
||||
this table are meaningless and should not be referenced).
|
||||
|
||||
This table is used to compute output lengths for the mp_toradix()
|
||||
function. Since a number n in radix r takes up about log_r(n)
|
||||
digits, we estimate the output size by taking the least integer
|
||||
greater than log_r(n), where:
|
||||
|
||||
log_r(n) = log_2(n) * log_r(2)
|
||||
|
||||
This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
|
||||
which are the output bases supported.
|
||||
*/
|
||||
|
||||
extern const float s_logv_2[];
|
||||
#define LOG_V_2(R) s_logv_2[(R)]
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
If MP_LOGTAB is not defined, use the math library to compute the
|
||||
logarithms on the fly. Otherwise, use the table.
|
||||
Pick which works best for your system.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#define LOG_V_2(R) (log(2.0)/log(R))
|
||||
|
||||
#endif /* if MP_LOGTAB */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Digit arithmetic macros */
|
||||
|
||||
/*
|
||||
When adding and multiplying digits, the results can be larger than
|
||||
can be contained in an mp_digit. Thus, an mp_word is used. These
|
||||
macros mask off the upper and lower digits of the mp_word (the
|
||||
mp_word may be more than 2 mp_digits wide, but we only concern
|
||||
ourselves with the low-order 2 mp_digits)
|
||||
*/
|
||||
|
||||
#define CARRYOUT(W) (mp_digit)((W)>>DIGIT_BIT)
|
||||
#define ACCUM(W) (mp_digit)(W)
|
||||
|
||||
#define MP_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MP_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define MP_HOWMANY(a,b) (((a) + (b) - 1)/(b))
|
||||
#define MP_ROUNDUP(a,b) (MP_HOWMANY(a,b) * (b))
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Comparison constants */
|
||||
|
||||
#define MP_LT -1
|
||||
#define MP_EQ 0
|
||||
#define MP_GT 1
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ private function declarations */
|
||||
|
||||
/*
|
||||
If MP_MACRO is false, these will be defined as actual functions;
|
||||
otherwise, suitable macro definitions will be used. This works
|
||||
around the fact that ANSI C89 doesn't support an 'inline' keyword
|
||||
(although I hear C9x will ... about bloody time). At present, the
|
||||
macro definitions are identical to the function bodies, but they'll
|
||||
expand in place, instead of generating a function call.
|
||||
|
||||
I chose these particular functions to be made into macros because
|
||||
some profiling showed they are called a lot on a typical workload,
|
||||
and yet they are primarily housekeeping.
|
||||
*/
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */
|
||||
void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
|
||||
void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */
|
||||
void s_mp_free(void *ptr); /* general free function */
|
||||
extern unsigned long mp_allocs;
|
||||
extern unsigned long mp_frees;
|
||||
extern unsigned long mp_copies;
|
||||
#else
|
||||
|
||||
/* Even if these are defined as macros, we need to respect the settings
|
||||
of the MP_MEMSET and MP_MEMCPY configuration options...
|
||||
*/
|
||||
#if MP_MEMSET == 0
|
||||
#define s_mp_setz(dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
|
||||
#else
|
||||
#define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMSET */
|
||||
|
||||
#if MP_MEMCPY == 0
|
||||
#define s_mp_copy(sp, dp, count) \
|
||||
{int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
|
||||
#else
|
||||
#define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
|
||||
#endif /* MP_MEMCPY */
|
||||
|
||||
#define s_mp_alloc(nb, ni) calloc(nb, ni)
|
||||
#define s_mp_free(ptr) {if(ptr) free(ptr);}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */
|
||||
mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */
|
||||
|
||||
#if MP_MACRO == 0
|
||||
void s_mp_clamp(mp_int *mp); /* clip leading zeroes */
|
||||
#else
|
||||
#define s_mp_clamp(mp)\
|
||||
{ mp_size used = MP_USED(mp); \
|
||||
while (used > 1 && DIGIT(mp, used - 1) == 0) --used; \
|
||||
MP_USED(mp) = used; \
|
||||
}
|
||||
#endif /* MP_MACRO */
|
||||
|
||||
void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */
|
||||
|
||||
mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */
|
||||
void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */
|
||||
mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place */
|
||||
void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */
|
||||
void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */
|
||||
void s_mp_div_2(mp_int *mp); /* divide by 2 in place */
|
||||
mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */
|
||||
mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd);
|
||||
/* normalize for division */
|
||||
mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */
|
||||
mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */
|
||||
mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */
|
||||
mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
|
||||
/* unsigned digit divide */
|
||||
mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);
|
||||
/* Barrett reduction */
|
||||
mp_err s_mp_add(mp_int *a, const mp_int *b); /* magnitude addition */
|
||||
mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_sub(mp_int *a, const mp_int *b); /* magnitude subtract */
|
||||
mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset);
|
||||
/* a += b * RADIX^offset */
|
||||
mp_err s_mp_mul(mp_int *a, const mp_int *b); /* magnitude multiply */
|
||||
#if MP_SQUARE
|
||||
mp_err s_mp_sqr(mp_int *a); /* magnitude square */
|
||||
#else
|
||||
#define s_mp_sqr(a) s_mp_mul(a, a)
|
||||
#endif
|
||||
mp_err s_mp_div(mp_int *rem, mp_int *div, mp_int *quot); /* magnitude div */
|
||||
mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */
|
||||
int s_mp_cmp(const mp_int *a, const mp_int *b); /* magnitude comparison */
|
||||
int s_mp_cmp_d(const mp_int *a, mp_digit d); /* magnitude digit compare */
|
||||
int s_mp_ispow2(const mp_int *v); /* is v a power of 2? */
|
||||
int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */
|
||||
|
||||
int s_mp_tovalue(char ch, int r); /* convert ch to value */
|
||||
char s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */
|
||||
int s_mp_outlen(int bits, int r); /* output length in bytes */
|
||||
mp_digit s_mp_invmod_radix(mp_digit P); /* returns (P ** -1) mod RADIX */
|
||||
mp_err s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err s_mp_invmod_2d( const mp_int *a, mp_size k, mp_int *c);
|
||||
mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
|
||||
/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */
|
||||
#if defined (__OS2__) && defined (__IBMC__)
|
||||
#define MPI_ASM_DECL __cdecl
|
||||
#else
|
||||
#define MPI_ASM_DECL
|
||||
#endif
|
||||
|
||||
#ifdef MPI_AMD64
|
||||
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_set_vec64(mp_digit*, mp_digit *, mp_size, mp_digit);
|
||||
mp_digit MPI_ASM_DECL s_mpv_mul_add_vec64(mp_digit*, const mp_digit*, mp_size, mp_digit);
|
||||
|
||||
/* c = a * b */
|
||||
#define s_mpv_mul_d(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_set_vec64(c, a, a_len, b)
|
||||
|
||||
/* c += a * b */
|
||||
#define s_mpv_mul_d_add(a, a_len, b, c) \
|
||||
((unsigned long*)c)[a_len] = s_mpv_mul_add_vec64(c, a, a_len, b)
|
||||
|
||||
#else
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c);
|
||||
|
||||
#endif
|
||||
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
|
||||
mp_size a_len, mp_digit b,
|
||||
mp_digit *c);
|
||||
void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
|
||||
mp_size a_len,
|
||||
mp_digit *sqrs);
|
||||
|
||||
mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo,
|
||||
mp_digit divisor, mp_digit *quot, mp_digit *rem);
|
||||
|
||||
/* c += a * b * (MP_RADIX ** offset); */
|
||||
#define s_mp_mul_d_add_offset(a, b, c, off) \
|
||||
(s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY)
|
||||
|
||||
typedef struct {
|
||||
mp_int N; /* modulus N */
|
||||
mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
|
||||
mp_size b; /* R == 2 ** b, also b = # significant bits in N */
|
||||
} mp_mont_modulus;
|
||||
|
||||
mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
|
||||
mp_mont_modulus *mmm);
|
||||
mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm);
|
||||
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* mpi.h
|
||||
*
|
||||
* Arbitrary precision integer arithmetic library
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Netscape Communications Corporation
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: mpi.h,v 1.22.8.1 2005-06-09 20:44:58 relyea%netscape.com Exp $ */
|
||||
|
||||
#ifndef _H_MPI_
|
||||
#define _H_MPI_
|
||||
|
||||
#include "mpi-config.h"
|
||||
|
||||
#if MP_DEBUG
|
||||
#undef MP_IOFUNC
|
||||
#define MP_IOFUNC 1
|
||||
#endif
|
||||
|
||||
#if MP_IOFUNC
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(BSDI)
|
||||
#undef ULLONG_MAX
|
||||
#endif
|
||||
|
||||
#if defined( macintosh )
|
||||
#include <Types.h>
|
||||
#elif defined( _WIN32_WCE)
|
||||
/* #include <sys/types.h> What do we need here ?? */
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define MP_NEG 1
|
||||
#define MP_ZPOS 0
|
||||
|
||||
#define MP_OKAY 0 /* no error, all is well */
|
||||
#define MP_YES 0 /* yes (boolean result) */
|
||||
#define MP_NO -1 /* no (boolean result) */
|
||||
#define MP_MEM -2 /* out of memory */
|
||||
#define MP_RANGE -3 /* argument out of range */
|
||||
#define MP_BADARG -4 /* invalid parameter */
|
||||
#define MP_UNDEF -5 /* answer is undefined */
|
||||
#define MP_LAST_CODE MP_UNDEF
|
||||
|
||||
typedef unsigned int mp_sign;
|
||||
typedef unsigned int mp_size;
|
||||
typedef int mp_err;
|
||||
|
||||
#define MP_32BIT_MAX 4294967295U
|
||||
|
||||
#if !defined(ULONG_MAX)
|
||||
#error "ULONG_MAX not defined"
|
||||
#elif !defined(UINT_MAX)
|
||||
#error "UINT_MAX not defined"
|
||||
#elif !defined(USHRT_MAX)
|
||||
#error "USHRT_MAX not defined"
|
||||
#endif
|
||||
|
||||
#if defined(ULONG_LONG_MAX) /* GCC, HPUX */
|
||||
#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
|
||||
#elif defined(ULLONG_MAX) /* Solaris */
|
||||
#define MP_ULONG_LONG_MAX ULLONG_MAX
|
||||
/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */
|
||||
#elif defined(ULONGLONG_MAX) /* IRIX, AIX */
|
||||
#define MP_ULONG_LONG_MAX ULONGLONG_MAX
|
||||
#endif
|
||||
|
||||
/* We only use unsigned long for mp_digit iff long is more than 32 bits. */
|
||||
#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX
|
||||
typedef unsigned long mp_digit;
|
||||
#define MP_DIGIT_MAX ULONG_MAX
|
||||
#define MP_DIGIT_FMT "%016lX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#define MP_USE_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
|
||||
#elif !defined(MP_USE_UINT_DIGIT) && defined(MP_ULONG_LONG_MAX)
|
||||
typedef unsigned long long mp_digit;
|
||||
#define MP_DIGIT_MAX MP_ULONG_LONG_MAX
|
||||
#define MP_DIGIT_FMT "%016llX" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX UINT_MAX
|
||||
#undef MP_NO_MP_WORD
|
||||
#define MP_NO_MP_WORD 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#define MP_USE_LONG_LONG_DIGIT 1
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
|
||||
#else
|
||||
typedef unsigned int mp_digit;
|
||||
#define MP_DIGIT_MAX UINT_MAX
|
||||
#define MP_DIGIT_FMT "%08X" /* printf() format for 1 digit */
|
||||
#define MP_HALF_DIGIT_MAX USHRT_MAX
|
||||
#undef MP_USE_UINT_DIGIT
|
||||
#define MP_USE_UINT_DIGIT 1
|
||||
#undef MP_USE_LONG_LONG_DIGIT
|
||||
#undef MP_USE_LONG_DIGIT
|
||||
#endif
|
||||
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
#if defined(MP_USE_UINT_DIGIT) && \
|
||||
(defined(MP_ULONG_LONG_MAX) || (ULONG_MAX > UINT_MAX))
|
||||
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
typedef unsigned long mp_word;
|
||||
typedef long mp_sword;
|
||||
#define MP_WORD_MAX ULONG_MAX
|
||||
|
||||
#else
|
||||
typedef unsigned long long mp_word;
|
||||
typedef long long mp_sword;
|
||||
#define MP_WORD_MAX MP_ULONG_LONG_MAX
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define MP_NO_MP_WORD 1
|
||||
#endif
|
||||
#endif /* !defined(MP_NO_MP_WORD) */
|
||||
|
||||
#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD)
|
||||
typedef unsigned int mp_word;
|
||||
typedef int mp_sword;
|
||||
#define MP_WORD_MAX UINT_MAX
|
||||
#endif
|
||||
|
||||
#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
|
||||
#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
|
||||
#define MP_RADIX (1+(mp_word)MP_DIGIT_MAX)
|
||||
|
||||
#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2)
|
||||
#define MP_HALF_RADIX (1+(mp_digit)MP_HALF_DIGIT_MAX)
|
||||
/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named
|
||||
** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's
|
||||
** consistent with the other _HALF_ names.
|
||||
*/
|
||||
|
||||
|
||||
/* Macros for accessing the mp_int internals */
|
||||
#define MP_SIGN(MP) ((MP)->sign)
|
||||
#define MP_USED(MP) ((MP)->used)
|
||||
#define MP_ALLOC(MP) ((MP)->alloc)
|
||||
#define MP_DIGITS(MP) ((MP)->dp)
|
||||
#define MP_DIGIT(MP,N) (MP)->dp[(N)]
|
||||
|
||||
/* This defines the maximum I/O base (minimum is 2) */
|
||||
#define MP_MAX_RADIX 64
|
||||
|
||||
typedef struct {
|
||||
mp_sign sign; /* sign of this quantity */
|
||||
mp_size alloc; /* how many digits allocated */
|
||||
mp_size used; /* how many digits used */
|
||||
mp_digit *dp; /* the digits themselves */
|
||||
} mp_int;
|
||||
|
||||
/* Default precision */
|
||||
mp_size mp_get_prec(void);
|
||||
void mp_set_prec(mp_size prec);
|
||||
|
||||
/* Memory management */
|
||||
mp_err mp_init(mp_int *mp);
|
||||
mp_err mp_init_size(mp_int *mp, mp_size prec);
|
||||
mp_err mp_init_copy(mp_int *mp, const mp_int *from);
|
||||
mp_err mp_copy(const mp_int *from, mp_int *to);
|
||||
void mp_exch(mp_int *mp1, mp_int *mp2);
|
||||
void mp_clear(mp_int *mp);
|
||||
void mp_zero(mp_int *mp);
|
||||
void mp_set(mp_int *mp, mp_digit d);
|
||||
mp_err mp_set_int(mp_int *mp, long z);
|
||||
#define mp_set_long(mp,z) mp_set_int(mp,z)
|
||||
mp_err mp_set_ulong(mp_int *mp, unsigned long z);
|
||||
|
||||
/* Single digit arithmetic */
|
||||
mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b);
|
||||
mp_err mp_mul_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
|
||||
mp_err mp_div_2(const mp_int *a, mp_int *c);
|
||||
mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c);
|
||||
|
||||
/* Sign manipulations */
|
||||
mp_err mp_abs(const mp_int *a, mp_int *b);
|
||||
mp_err mp_neg(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Full arithmetic */
|
||||
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqr(const mp_int *a, mp_int *b);
|
||||
#else
|
||||
#define mp_sqr(a, b) mp_mul(a, a, b)
|
||||
#endif
|
||||
mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r);
|
||||
mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r);
|
||||
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_2expt(mp_int *a, mp_digit k);
|
||||
mp_err mp_sqrt(const mp_int *a, mp_int *b);
|
||||
|
||||
/* Modular arithmetic */
|
||||
#if MP_MODARITH
|
||||
mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c);
|
||||
mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
#if MP_SQUARE
|
||||
mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#else
|
||||
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
|
||||
#endif
|
||||
mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
|
||||
mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
|
||||
#endif /* MP_MODARITH */
|
||||
|
||||
/* Comparisons */
|
||||
int mp_cmp_z(const mp_int *a);
|
||||
int mp_cmp_d(const mp_int *a, mp_digit d);
|
||||
int mp_cmp(const mp_int *a, const mp_int *b);
|
||||
int mp_cmp_mag(mp_int *a, mp_int *b);
|
||||
int mp_cmp_int(const mp_int *a, long z);
|
||||
int mp_isodd(const mp_int *a);
|
||||
int mp_iseven(const mp_int *a);
|
||||
|
||||
/* Number theoretic */
|
||||
#if MP_NUMTH
|
||||
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
|
||||
mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
|
||||
mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
|
||||
#endif /* end MP_NUMTH */
|
||||
|
||||
/* Input and output */
|
||||
#if MP_IOFUNC
|
||||
void mp_print(mp_int *mp, FILE *ofp);
|
||||
#endif /* end MP_IOFUNC */
|
||||
|
||||
/* Base conversion */
|
||||
mp_err mp_read_raw(mp_int *mp, char *str, int len);
|
||||
int mp_raw_size(mp_int *mp);
|
||||
mp_err mp_toraw(mp_int *mp, char *str);
|
||||
mp_err mp_read_radix(mp_int *mp, const char *str, int radix);
|
||||
mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix);
|
||||
int mp_radix_size(mp_int *mp, int radix);
|
||||
mp_err mp_toradix(mp_int *mp, char *str, int radix);
|
||||
int mp_tovalue(char ch, int r);
|
||||
|
||||
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
|
||||
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
|
||||
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
|
||||
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
|
||||
|
||||
/* Error strings */
|
||||
const char *mp_strerror(mp_err ec);
|
||||
|
||||
/* Octet string conversion functions */
|
||||
mp_err mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len);
|
||||
int mp_unsigned_octet_size(const mp_int *mp);
|
||||
mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
|
||||
mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size len);
|
||||
|
||||
/* Miscellaneous */
|
||||
mp_size mp_trailing_zeros(const mp_int *mp);
|
||||
|
||||
#define MP_CHECKOK(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
#define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP
|
||||
|
||||
#if defined(MP_API_COMPATIBLE)
|
||||
#define NEG MP_NEG
|
||||
#define ZPOS MP_ZPOS
|
||||
#define DIGIT_MAX MP_DIGIT_MAX
|
||||
#define DIGIT_BIT MP_DIGIT_BIT
|
||||
#define DIGIT_FMT MP_DIGIT_FMT
|
||||
#define RADIX MP_RADIX
|
||||
#define MAX_RADIX MP_MAX_RADIX
|
||||
#define SIGN(MP) MP_SIGN(MP)
|
||||
#define USED(MP) MP_USED(MP)
|
||||
#define ALLOC(MP) MP_ALLOC(MP)
|
||||
#define DIGITS(MP) MP_DIGITS(MP)
|
||||
#define DIGIT(MP,N) MP_DIGIT(MP,N)
|
||||
|
||||
#if MP_ARGCHK == 1
|
||||
#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
|
||||
#elif MP_ARGCHK == 2
|
||||
#include <assert.h>
|
||||
#define ARGCHK(X,Y) assert(X)
|
||||
#else
|
||||
#define ARGCHK(X,Y) /* */
|
||||
#endif
|
||||
#endif /* defined MP_API_COMPATIBLE */
|
||||
|
||||
/*
|
||||
* mpi_getProcessorLineSize() returns the size in bytes of the cache line
|
||||
* if a cache exists, or zero if there is no cache. If more than one
|
||||
* cache line exists, it should return the smallest line size (which is
|
||||
* usually the L1 cache).
|
||||
*
|
||||
* mp_modexp uses this information to make sure that private key information
|
||||
* isn't being leaked through the cache.
|
||||
*
|
||||
* see mpcpucache.c for the implementation.
|
||||
*/
|
||||
unsigned long mpi_getProcessorLineSize();
|
||||
|
||||
#endif /* end _H_MPI_ */
|
||||
@@ -1,65 +0,0 @@
|
||||
/* ***** 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 Solaris software cryptographic token.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* 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 MPI_AMD64
|
||||
#error This file only works on AMD64 platforms.
|
||||
#endif
|
||||
|
||||
#include <mpi-priv.h>
|
||||
|
||||
/*
|
||||
* MPI glue
|
||||
*
|
||||
*/
|
||||
|
||||
/* Presently, this is only used by the Montgomery arithmetic code. */
|
||||
/* c += a * b */
|
||||
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len,
|
||||
mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit w;
|
||||
mp_digit d;
|
||||
|
||||
d = s_mpv_mul_add_vec64(c, a, a_len, b);
|
||||
c += a_len;
|
||||
while (d) {
|
||||
w = c[0] + d;
|
||||
d = (w < c[0] || w < d);
|
||||
*c++ = w;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,418 +0,0 @@
|
||||
# ***** 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 Solaris software cryptographic token.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Sun Microsystems, Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Sun Microsystems, Inc.
|
||||
#
|
||||
# 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 ***** */
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Implementation of s_mpv_mul_set_vec which exploits
|
||||
# the 64X64->128 bit unsigned multiply instruction.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
# r = a * digit, r and a are vectors of length len
|
||||
# returns the carry digit
|
||||
# r and a are 64 bit aligned.
|
||||
#
|
||||
# uint64_t
|
||||
# s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
#
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
|
||||
|
||||
xorq %rax, %rax # if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L17
|
||||
|
||||
movq %rdx, %r8 # Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 # cy = 0
|
||||
|
||||
.L15:
|
||||
cmpq $8, %r8 # 8 - len
|
||||
jb .L16
|
||||
movq 0(%rsi), %rax # rax = a[0]
|
||||
movq 8(%rsi), %r11 # prefetch a[1]
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 # prefetch a[2]
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 # prefetch a[3]
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 # prefetch a[4]
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 # prefetch a[5]
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 # prefetch a[6]
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 # prefetch a[7]
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx # p = a[7] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 56(%rdi) # r[7] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L17
|
||||
jmp .L15
|
||||
|
||||
.L16:
|
||||
movq 0(%rsi), %rax
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
|
||||
.L17:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_set_vec64, [.-s_mpv_mul_set_vec64]
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
#
|
||||
# Implementation of s_mpv_mul_add_vec which exploits
|
||||
# the 64X64->128 bit unsigned multiply instruction.
|
||||
#
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
# r += a * digit, r and a are vectors of length len
|
||||
# returns the carry digit
|
||||
# r and a are 64 bit aligned.
|
||||
#
|
||||
# uint64_t
|
||||
# s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
#
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
|
||||
|
||||
xorq %rax, %rax # if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L27
|
||||
|
||||
movq %rdx, %r8 # Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 # cy = 0
|
||||
|
||||
.L25:
|
||||
cmpq $8, %r8 # 8 - len
|
||||
jb .L26
|
||||
movq 0(%rsi), %rax # rax = a[0]
|
||||
movq 0(%rdi), %r10 # r10 = r[0]
|
||||
movq 8(%rsi), %r11 # prefetch a[1]
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[0]
|
||||
movq 8(%rdi), %r10 # prefetch r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 # prefetch a[2]
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[1]
|
||||
movq 16(%rdi), %r10 # prefetch r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 # prefetch a[3]
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[2]
|
||||
movq 24(%rdi), %r10 # prefetch r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 # prefetch a[4]
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[3]
|
||||
movq 32(%rdi), %r10 # prefetch r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 # prefetch a[5]
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[4]
|
||||
movq 40(%rdi), %r10 # prefetch r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 # prefetch a[6]
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[5]
|
||||
movq 48(%rdi), %r10 # prefetch r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 # prefetch a[7]
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[6]
|
||||
movq 56(%rdi), %r10 # prefetch r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx # p = a[7] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 56(%rdi) # r[7] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L27
|
||||
jmp .L25
|
||||
|
||||
.L26:
|
||||
movq 0(%rsi), %rax
|
||||
movq 0(%rdi), %r10
|
||||
mulq %rcx # p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[0]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 0(%rdi) # r[0] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
movq 8(%rdi), %r10
|
||||
mulq %rcx # p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 8(%rdi) # r[1] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
movq 16(%rdi), %r10
|
||||
mulq %rcx # p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 16(%rdi) # r[2] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
movq 24(%rdi), %r10
|
||||
mulq %rcx # p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 24(%rdi) # r[3] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
movq 32(%rdi), %r10
|
||||
mulq %rcx # p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 32(%rdi) # r[4] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
movq 40(%rdi), %r10
|
||||
mulq %rcx # p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 40(%rdi) # r[5] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
movq 48(%rdi), %r10
|
||||
mulq %rcx # p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx # p += r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx # p += cy
|
||||
movq %rax, 48(%rdi) # r[6] = lo(p)
|
||||
movq %rdx, %r9 # cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
|
||||
.L27:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_add_vec64, [.-s_mpv_mul_add_vec64]
|
||||
@@ -1,418 +0,0 @@
|
||||
/ ***** 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 Solaris software cryptographic token.
|
||||
/
|
||||
/ The Initial Developer of the Original Code is
|
||||
/ Sun Microsystems, Inc.
|
||||
/ Portions created by the Initial Developer are Copyright (C) 2005
|
||||
/ the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/ Sun Microsystems, Inc.
|
||||
/
|
||||
/ 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 ***** */
|
||||
|
||||
|
||||
/ ------------------------------------------------------------------------
|
||||
/
|
||||
/ Implementation of s_mpv_mul_set_vec which exploits
|
||||
/ the 64X64->128 bit unsigned multiply instruction.
|
||||
/
|
||||
/ ------------------------------------------------------------------------
|
||||
|
||||
/ r = a * digit, r and a are vectors of length len
|
||||
/ returns the carry digit
|
||||
/ r and a are 64 bit aligned.
|
||||
/
|
||||
/ uint64_t
|
||||
/ s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
/
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
|
||||
|
||||
xorq %rax, %rax / if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L17
|
||||
|
||||
movq %rdx, %r8 / Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 / cy = 0
|
||||
|
||||
.L15:
|
||||
cmpq $8, %r8 / 8 - len
|
||||
jb .L16
|
||||
movq 0(%rsi), %rax / rax = a[0]
|
||||
movq 8(%rsi), %r11 / prefetch a[1]
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 / prefetch a[2]
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 / prefetch a[3]
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 / prefetch a[4]
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 / prefetch a[5]
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 / prefetch a[6]
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 / prefetch a[7]
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx / p = a[7] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 56(%rdi) / r[7] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L17
|
||||
jmp .L15
|
||||
|
||||
.L16:
|
||||
movq 0(%rsi), %rax
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L17
|
||||
|
||||
|
||||
.L17:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_set_vec64, [.-s_mpv_mul_set_vec64]
|
||||
|
||||
/ ------------------------------------------------------------------------
|
||||
/
|
||||
/ Implementation of s_mpv_mul_add_vec which exploits
|
||||
/ the 64X64->128 bit unsigned multiply instruction.
|
||||
/
|
||||
/ ------------------------------------------------------------------------
|
||||
|
||||
/ r += a * digit, r and a are vectors of length len
|
||||
/ returns the carry digit
|
||||
/ r and a are 64 bit aligned.
|
||||
/
|
||||
/ uint64_t
|
||||
/ s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
|
||||
/
|
||||
|
||||
.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
|
||||
|
||||
xorq %rax, %rax / if (len == 0) return (0)
|
||||
testq %rdx, %rdx
|
||||
jz .L27
|
||||
|
||||
movq %rdx, %r8 / Use r8 for len; %rdx is used by mul
|
||||
xorq %r9, %r9 / cy = 0
|
||||
|
||||
.L25:
|
||||
cmpq $8, %r8 / 8 - len
|
||||
jb .L26
|
||||
movq 0(%rsi), %rax / rax = a[0]
|
||||
movq 0(%rdi), %r10 / r10 = r[0]
|
||||
movq 8(%rsi), %r11 / prefetch a[1]
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[0]
|
||||
movq 8(%rdi), %r10 / prefetch r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 16(%rsi), %r11 / prefetch a[2]
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[1]
|
||||
movq 16(%rdi), %r10 / prefetch r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 24(%rsi), %r11 / prefetch a[3]
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[2]
|
||||
movq 24(%rdi), %r10 / prefetch r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 32(%rsi), %r11 / prefetch a[4]
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[3]
|
||||
movq 32(%rdi), %r10 / prefetch r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 40(%rsi), %r11 / prefetch a[5]
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[4]
|
||||
movq 40(%rdi), %r10 / prefetch r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 48(%rsi), %r11 / prefetch a[6]
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[5]
|
||||
movq 48(%rdi), %r10 / prefetch r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
movq 56(%rsi), %r11 / prefetch a[7]
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[6]
|
||||
movq 56(%rdi), %r10 / prefetch r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
movq %r11, %rax
|
||||
mulq %rcx / p = a[7] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[7]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 56(%rdi) / r[7] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
|
||||
addq $64, %rsi
|
||||
addq $64, %rdi
|
||||
subq $8, %r8
|
||||
|
||||
jz .L27
|
||||
jmp .L25
|
||||
|
||||
.L26:
|
||||
movq 0(%rsi), %rax
|
||||
movq 0(%rdi), %r10
|
||||
mulq %rcx / p = a[0] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[0]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 0(%rdi) / r[0] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 8(%rsi), %rax
|
||||
movq 8(%rdi), %r10
|
||||
mulq %rcx / p = a[1] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[1]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 8(%rdi) / r[1] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 16(%rsi), %rax
|
||||
movq 16(%rdi), %r10
|
||||
mulq %rcx / p = a[2] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[2]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 16(%rdi) / r[2] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 24(%rsi), %rax
|
||||
movq 24(%rdi), %r10
|
||||
mulq %rcx / p = a[3] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[3]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 24(%rdi) / r[3] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 32(%rsi), %rax
|
||||
movq 32(%rdi), %r10
|
||||
mulq %rcx / p = a[4] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[4]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 32(%rdi) / r[4] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 40(%rsi), %rax
|
||||
movq 40(%rdi), %r10
|
||||
mulq %rcx / p = a[5] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[5]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 40(%rdi) / r[5] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
movq 48(%rsi), %rax
|
||||
movq 48(%rdi), %r10
|
||||
mulq %rcx / p = a[6] * digit
|
||||
addq %r10, %rax
|
||||
adcq $0, %rdx / p += r[6]
|
||||
addq %r9, %rax
|
||||
adcq $0, %rdx / p += cy
|
||||
movq %rax, 48(%rdi) / r[6] = lo(p)
|
||||
movq %rdx, %r9 / cy = hi(p)
|
||||
decq %r8
|
||||
jz .L27
|
||||
|
||||
|
||||
.L27:
|
||||
movq %r9, %rax
|
||||
ret
|
||||
|
||||
.size s_mpv_mul_add_vec64, [.-s_mpv_mul_add_vec64]
|
||||
@@ -1,115 +0,0 @@
|
||||
/* ***** 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 Netscape security libraries.
|
||||
*
|
||||
* 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):
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: mpi_hp.c,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* This file contains routines that perform vector multiplication. */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
/* #include <sys/systeminfo.h> */
|
||||
#include <strings.h>
|
||||
|
||||
extern void multacc512(
|
||||
int length, /* doublewords in multiplicand vector. */
|
||||
const mp_digit *scalaraddr, /* Address of scalar. */
|
||||
const mp_digit *multiplicand, /* The multiplicand vector. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
extern void maxpy_little(
|
||||
int length, /* doublewords in multiplicand vector. */
|
||||
const mp_digit *scalaraddr, /* Address of scalar. */
|
||||
const mp_digit *multiplicand, /* The multiplicand vector. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
extern void add_diag_little(
|
||||
int length, /* doublewords in input vector. */
|
||||
const mp_digit *root, /* The vector to square. */
|
||||
mp_digit * result); /* Where to accumulate the result. */
|
||||
|
||||
void
|
||||
s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
|
||||
{
|
||||
add_diag_little(a_len, pa, ps);
|
||||
}
|
||||
|
||||
#define MAX_STACK_DIGITS 258
|
||||
#define MULTACC512_LEN (512 / MP_DIGIT_BIT)
|
||||
#define HP_MPY_ADD_FN (a_len == MULTACC512_LEN ? multacc512 : maxpy_little)
|
||||
|
||||
/* c = a * b */
|
||||
void
|
||||
s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit x[MAX_STACK_DIGITS];
|
||||
mp_digit *px = x;
|
||||
size_t xSize = 0;
|
||||
|
||||
if (a == c) {
|
||||
if (a_len > MAX_STACK_DIGITS) {
|
||||
xSize = sizeof(mp_digit) * (a_len + 2);
|
||||
px = malloc(xSize);
|
||||
if (!px)
|
||||
return;
|
||||
}
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
}
|
||||
s_mp_setz(c, a_len + 1);
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
if (px != x && px) {
|
||||
memset(px, 0, xSize);
|
||||
free(px);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is a_len words long. */
|
||||
void
|
||||
s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
c[a_len] = 0; /* so carry propagation stops here. */
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
}
|
||||
|
||||
/* c += a * b, where a is y words long. */
|
||||
void
|
||||
s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
mp_digit *c)
|
||||
{
|
||||
HP_MPY_ADD_FN(a_len, &b, a, c);
|
||||
}
|
||||
|
||||
@@ -1,342 +0,0 @@
|
||||
/
|
||||
/ 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 Netscape security libraries.
|
||||
/
|
||||
/ The Initial Developer of the Original Code is Netscape
|
||||
/ Communications Corporation. Portions created by Netscape are
|
||||
/ Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
/ Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/ $Id: mpi_i86pc.s,v 1.1 2001-04-27 20:47:39 nelsonb%netscape.com Exp $
|
||||
/
|
||||
|
||||
.text
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d
|
||||
.type s_mpv_mul_d,@function
|
||||
s_mpv_mul_d:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L2 / jmp if a_len == 0
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
cld
|
||||
L1:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L1 / jmp if a_len != 0
|
||||
L2:
|
||||
mov %ebx,0(%edi) / *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d_add
|
||||
.type s_mpv_mul_d_add,@function
|
||||
s_mpv_mul_d_add:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L4 / jmp if a_len == 0
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
cld
|
||||
L3:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx / add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L3 / jmp if a_len != 0
|
||||
L4:
|
||||
mov %ebx,0(%edi) / *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 36: caller's esi
|
||||
/ ebp - 32: caller's edi
|
||||
/ ebp - 28:
|
||||
/ ebp - 24:
|
||||
/ ebp - 20:
|
||||
/ ebp - 16:
|
||||
/ ebp - 12:
|
||||
/ ebp - 8:
|
||||
/ ebp - 4:
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: a argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: b argument
|
||||
/ ebp + 20: c argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
.type s_mpv_mul_d_add_prop,@function
|
||||
s_mpv_mul_d_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je L6 / jmp if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi / esi = a
|
||||
L5:
|
||||
lodsl / eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx / edx = b
|
||||
mull %edx / edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax / add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx / add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx / high half of product becomes next carry
|
||||
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L5 / jmp if a_len != 0
|
||||
L6:
|
||||
cmp $0,%ebx / is carry zero?
|
||||
jz L8
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jnc L8
|
||||
L7:
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jc L7
|
||||
L8:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/ ebp - 20: caller's esi
|
||||
/ ebp - 16: caller's edi
|
||||
/ ebp - 12:
|
||||
/ ebp - 8: carry
|
||||
/ ebp - 4: a_len local
|
||||
/ ebp + 0: caller's ebp
|
||||
/ ebp + 4: return address
|
||||
/ ebp + 8: pa argument
|
||||
/ ebp + 12: a_len argument
|
||||
/ ebp + 16: ps argument
|
||||
/ ebp + 20:
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
|
||||
.globl s_mpv_sqr_add_prop
|
||||
.type s_mpv_sqr_add_prop,@function
|
||||
s_mpv_sqr_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $12,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx / carry = 0
|
||||
mov 12(%ebp),%ecx / a_len
|
||||
mov 16(%ebp),%edi / edi = ps
|
||||
cmp $0,%ecx
|
||||
je L11 / jump if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi / esi = pa
|
||||
L10:
|
||||
lodsl / %eax = [ds:si]; si += 4;
|
||||
mull %eax
|
||||
|
||||
add %ebx,%eax / add "carry"
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx
|
||||
add %ebx,%eax / add low word from result
|
||||
mov 4(%edi),%ebx
|
||||
stosl / [es:di] = %eax; di += 4;
|
||||
adc %ebx,%edx / add high word from result
|
||||
movl $0,%ebx
|
||||
mov %edx,%eax
|
||||
adc $0,%ebx
|
||||
stosl / [es:di] = %eax; di += 4;
|
||||
dec %ecx / --a_len
|
||||
jnz L10 / jmp if a_len != 0
|
||||
L11:
|
||||
cmp $0,%ebx / is carry zero?
|
||||
jz L14
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jnc L14
|
||||
L12:
|
||||
mov 0(%edi),%eax / add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl / [es:edi] = ax; edi += 4;
|
||||
jc L12
|
||||
L14:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
/
|
||||
/ Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
/ so its high bit is 1. This code is from NSPR.
|
||||
/
|
||||
/ mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
/ mp_digit *qp, mp_digit *rp)
|
||||
|
||||
/ esp + 0: Caller's ebx
|
||||
/ esp + 4: return address
|
||||
/ esp + 8: Nhi argument
|
||||
/ esp + 12: Nlo argument
|
||||
/ esp + 16: divisor argument
|
||||
/ esp + 20: qp argument
|
||||
/ esp + 24: rp argument
|
||||
/ registers:
|
||||
/ eax:
|
||||
/ ebx: carry
|
||||
/ ecx: a_len
|
||||
/ edx:
|
||||
/ esi: a ptr
|
||||
/ edi: c ptr
|
||||
/
|
||||
|
||||
.globl s_mpv_div_2dx1d
|
||||
.type s_mpv_div_2dx1d,@function
|
||||
s_mpv_div_2dx1d:
|
||||
push %ebx
|
||||
mov 8(%esp),%edx
|
||||
mov 12(%esp),%eax
|
||||
mov 16(%esp),%ebx
|
||||
div %ebx
|
||||
mov 20(%esp),%ebx
|
||||
mov %eax,0(%ebx)
|
||||
mov 24(%esp),%ebx
|
||||
mov %edx,0(%ebx)
|
||||
xor %eax,%eax / return zero
|
||||
pop %ebx
|
||||
ret
|
||||
nop
|
||||
|
||||
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* 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 Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
* $Id: mpi_mips.s,v 1.2 2000-08-31 02:40:32 nelsonb%netscape.com Exp $
|
||||
*/
|
||||
#include <regdef.h>
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.section .text, 1, 0x00000006, 4, 4
|
||||
.text:
|
||||
.section .text
|
||||
|
||||
.ent s_mpv_mul_d_add
|
||||
.globl s_mpv_mul_d_add
|
||||
|
||||
s_mpv_mul_d_add:
|
||||
#/* c += a * b */
|
||||
#void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit c0, c1; regs a6, a7
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.L.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.L.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.L.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.L.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4 #
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.L.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.L.3:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.L.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .L.6
|
||||
addiu a3,a3,4
|
||||
# } else {
|
||||
.L.5:
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
b .L.6
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
# } else {
|
||||
.L.2:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += c0;
|
||||
mflo t0
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
.L.6:
|
||||
# c[1] = cy;
|
||||
jr ra
|
||||
sw t2,4(a3)
|
||||
# }
|
||||
.L.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d_add
|
||||
|
||||
.ent s_mpv_mul_d_add_prop
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
|
||||
s_mpv_mul_d_add_prop:
|
||||
#/* c += a * b */
|
||||
#void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit c0, c1; regs a6, a7
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.M.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.M.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.M.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.M.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4 #
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.M.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.M.3:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.M.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# c1 = c[1];
|
||||
lwu a7,4(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# w1 += c1;
|
||||
daddu t1,t1,a7
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .M.6
|
||||
addiu a3,a3,8
|
||||
# } else {
|
||||
.M.5:
|
||||
# w0 += c0;
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
b .M.6
|
||||
addiu a3,a3,4
|
||||
# }
|
||||
# } else {
|
||||
.M.2:
|
||||
# c0 = c[0];
|
||||
lwu a6,0(a3)
|
||||
# w0 += c0;
|
||||
mflo t0
|
||||
daddu t0,t0,a6
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
addiu a3,a3,4
|
||||
# }
|
||||
.M.6:
|
||||
|
||||
# while (cy) {
|
||||
beq t2,zero,.M.1
|
||||
nop
|
||||
.M.7:
|
||||
# mp_word w = (mp_word)*c + cy;
|
||||
lwu a6,0(a3)
|
||||
daddu t2,t2,a6
|
||||
# *c++ = ACCUM(w);
|
||||
sw t2,0(a3)
|
||||
# cy = CARRYOUT(w);
|
||||
dsrl32 t2,t2,0
|
||||
bne t2,zero,.M.7
|
||||
addiu a3,a3,4
|
||||
|
||||
# }
|
||||
.M.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d_add_prop
|
||||
|
||||
.ent s_mpv_mul_d
|
||||
.globl s_mpv_mul_d
|
||||
|
||||
s_mpv_mul_d:
|
||||
#/* c = a * b */
|
||||
#void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
# mp_digit *c)
|
||||
#{
|
||||
# mp_digit a0, a1; regs a4, a5
|
||||
# mp_digit cy = 0; reg t2
|
||||
# mp_word w0, w1; regs t0, t1
|
||||
#
|
||||
# if (a_len) {
|
||||
beq a1,zero,.N.1
|
||||
move t2,zero # cy = 0
|
||||
dsll32 a2,a2,0 # "b" is sometimes negative (?!?!)
|
||||
dsrl32 a2,a2,0 # This clears the upper 32 bits.
|
||||
# a0 = a[0];
|
||||
lwu a4,0(a0)
|
||||
# w0 = ((mp_word)b * a0);
|
||||
dmultu a2,a4
|
||||
# if (--a_len) {
|
||||
addiu a1,a1,-1
|
||||
beq a1,zero,.N.2
|
||||
# while (a_len >= 2) {
|
||||
sltiu t3,a1,2
|
||||
bne t3,zero,.N.3
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
.N.4:
|
||||
# a_len -= 2;
|
||||
addiu a1,a1,-2
|
||||
# w0 += cy;
|
||||
mflo t0
|
||||
daddu t0,t0,t2
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# a0 = a[2];
|
||||
lwu a4,8(a0)
|
||||
# a += 2;
|
||||
addiu a0,a0,8
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# w0 = (mp_word)b * a0;
|
||||
dmultu a2,a4
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# c += 2;
|
||||
addiu a3,a3,8
|
||||
sltiu t3,a1,2
|
||||
beq t3,zero,.N.4
|
||||
# a1 = a[1];
|
||||
lwu a5,4(a0)
|
||||
# }
|
||||
.N.3:
|
||||
# w0 += cy;
|
||||
# if (a_len) {
|
||||
mflo t0
|
||||
beq a1,zero,.N.5
|
||||
daddu t0,t0,t2
|
||||
# w1 = (mp_word)b * a1;
|
||||
dmultu a2,a5 #
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# w1 += cy;
|
||||
mflo t1
|
||||
daddu t1,t1,t2
|
||||
# c[1] = ACCUM(w1);
|
||||
sw t1,4(a3)
|
||||
# cy = CARRYOUT(w1);
|
||||
dsrl32 t2,t1,0
|
||||
# c += 1;
|
||||
b .N.6
|
||||
addiu a3,a3,4
|
||||
# } else {
|
||||
.N.5:
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
b .N.6
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
# } else {
|
||||
.N.2:
|
||||
mflo t0
|
||||
# c[0] = ACCUM(w0);
|
||||
sw t0,0(a3)
|
||||
# cy = CARRYOUT(w0);
|
||||
dsrl32 t2,t0,0
|
||||
# }
|
||||
.N.6:
|
||||
# c[1] = cy;
|
||||
jr ra
|
||||
sw t2,4(a3)
|
||||
# }
|
||||
.N.1:
|
||||
jr ra
|
||||
nop
|
||||
#}
|
||||
#
|
||||
.end s_mpv_mul_d
|
||||
|
||||
|
||||
.ent s_mpv_sqr_add_prop
|
||||
.globl s_mpv_sqr_add_prop
|
||||
#void s_mpv_sqr_add_prop(const mp_digit *a, mp_size a_len, mp_digit *sqrs);
|
||||
# registers
|
||||
# a0 *a
|
||||
# a1 a_len
|
||||
# a2 *sqr
|
||||
# a3 digit from *a, a_i
|
||||
# a4 square of digit from a
|
||||
# a5,a6 next 2 digits in sqr
|
||||
# a7,t0 carry
|
||||
s_mpv_sqr_add_prop:
|
||||
move a7,zero
|
||||
move t0,zero
|
||||
lwu a3,0(a0)
|
||||
addiu a1,a1,-1 # --a_len
|
||||
dmultu a3,a3
|
||||
beq a1,zero,.P.3 # jump if we've already done the only sqr
|
||||
addiu a0,a0,4 # ++a
|
||||
.P.2:
|
||||
lwu a5,0(a2)
|
||||
lwu a6,4(a2)
|
||||
addiu a2,a2,8 # sqrs += 2;
|
||||
dsll32 a6,a6,0
|
||||
daddu a5,a5,a6
|
||||
lwu a3,0(a0)
|
||||
addiu a0,a0,4 # ++a
|
||||
mflo a4
|
||||
daddu a6,a5,a4
|
||||
sltu a7,a6,a5 # a7 = a6 < a5 detect overflow
|
||||
dmultu a3,a3
|
||||
daddu a4,a6,t0
|
||||
sltu t0,a4,a6
|
||||
add t0,t0,a7
|
||||
sw a4,-8(a2)
|
||||
addiu a1,a1,-1 # --a_len
|
||||
dsrl32 a4,a4,0
|
||||
bne a1,zero,.P.2 # loop if a_len > 0
|
||||
sw a4,-4(a2)
|
||||
.P.3:
|
||||
lwu a5,0(a2)
|
||||
lwu a6,4(a2)
|
||||
addiu a2,a2,8 # sqrs += 2;
|
||||
dsll32 a6,a6,0
|
||||
daddu a5,a5,a6
|
||||
mflo a4
|
||||
daddu a6,a5,a4
|
||||
sltu a7,a6,a5 # a7 = a6 < a5 detect overflow
|
||||
daddu a4,a6,t0
|
||||
sltu t0,a4,a6
|
||||
add t0,t0,a7
|
||||
sw a4,-8(a2)
|
||||
beq t0,zero,.P.9 # jump if no carry
|
||||
dsrl32 a4,a4,0
|
||||
.P.8:
|
||||
sw a4,-4(a2)
|
||||
/* propagate final carry */
|
||||
lwu a5,0(a2)
|
||||
daddu a6,a5,t0
|
||||
sltu t0,a6,a5
|
||||
bne t0,zero,.P.8 # loop if carry persists
|
||||
addiu a2,a2,4 # sqrs++
|
||||
.P.9:
|
||||
jr ra
|
||||
sw a4,-4(a2)
|
||||
|
||||
.end s_mpv_sqr_add_prop
|
||||
@@ -1,361 +0,0 @@
|
||||
/* ***** 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 Netscape security libraries.
|
||||
*
|
||||
* 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):
|
||||
*
|
||||
* 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 ***** */
|
||||
/* $Id: mpi_sparc.c,v 1.6 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
/* Multiplication performance enhancements for sparc v8+vis CPUs. */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include <stddef.h>
|
||||
#include <sys/systeminfo.h>
|
||||
#include <strings.h>
|
||||
|
||||
/* In the functions below, */
|
||||
/* vector y must be 8-byte aligned, and n must be even */
|
||||
/* returns carry out of high order word of result */
|
||||
/* maximum n is 256 */
|
||||
|
||||
/* vector x += vector y * scaler a; where y is of length n words. */
|
||||
extern mp_digit mul_add_inp(mp_digit *x, const mp_digit *y, int n, mp_digit a);
|
||||
|
||||
/* vector z = vector x + vector y * scaler a; where y is of length n words. */
|
||||
extern mp_digit mul_add(mp_digit *z, const mp_digit *x, const mp_digit *y,
|
||||
int n, mp_digit a);
|
||||
|
||||
/* v8 versions of these functions run on any Sparc v8 CPU. */
|
||||
|
||||
/* This trick works on Sparc V8 CPUs with the Workshop compilers. */
|
||||
#define MP_MUL_DxD(a, b, Phi, Plo) \
|
||||
{ unsigned long long product = (unsigned long long)a * b; \
|
||||
Plo = (mp_digit)product; \
|
||||
Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
|
||||
|
||||
/* c = a * b */
|
||||
static void
|
||||
v8_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
*c = d;
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
*c = carry;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* c += a * b */
|
||||
static void
|
||||
v8_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + *c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
*c = d;
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
a0b0 += a_i = *c;
|
||||
if (a0b0 < a_i)
|
||||
++a1b1;
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
*c = carry;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Presently, this is only used by the Montgomery arithmetic code. */
|
||||
/* c += a * b */
|
||||
static void
|
||||
v8_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
#if !defined(MP_NO_MP_WORD)
|
||||
mp_digit d = 0;
|
||||
|
||||
/* Inner product: Digits of a */
|
||||
while (a_len--) {
|
||||
mp_word w = ((mp_word)b * *a++) + *c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
|
||||
while (d) {
|
||||
mp_word w = (mp_word)*c + d;
|
||||
*c++ = ACCUM(w);
|
||||
d = CARRYOUT(w);
|
||||
}
|
||||
#else
|
||||
mp_digit carry = 0;
|
||||
while (a_len--) {
|
||||
mp_digit a_i = *a++;
|
||||
mp_digit a0b0, a1b1;
|
||||
|
||||
MP_MUL_DxD(a_i, b, a1b1, a0b0);
|
||||
|
||||
a0b0 += carry;
|
||||
if (a0b0 < carry)
|
||||
++a1b1;
|
||||
|
||||
a0b0 += a_i = *c;
|
||||
if (a0b0 < a_i)
|
||||
++a1b1;
|
||||
|
||||
*c++ = a0b0;
|
||||
carry = a1b1;
|
||||
}
|
||||
while (carry) {
|
||||
mp_digit c_i = *c;
|
||||
carry += c_i;
|
||||
*c++ = carry;
|
||||
carry = carry < c_i;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* vis versions of these functions run only on v8+vis or v9+vis CPUs. */
|
||||
|
||||
/* c = a * b */
|
||||
static void
|
||||
vis_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (a == c || ((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
s_mp_setz(c, a_len + 1);
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
c[a_len] = d;
|
||||
} else {
|
||||
v8_mpv_mul_d(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is a_len words long. */
|
||||
static void
|
||||
vis_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
c[a_len] = d;
|
||||
} else {
|
||||
v8_mpv_mul_d_add(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* c += a * b, where a is y words long. */
|
||||
static void
|
||||
vis_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b,
|
||||
mp_digit *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_digit x[258];
|
||||
if (a_len <= 256) {
|
||||
if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
|
||||
mp_digit * px;
|
||||
px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
|
||||
memcpy(px, a, a_len * sizeof(*a));
|
||||
a = px;
|
||||
if (a_len & 1) {
|
||||
px[a_len] = 0;
|
||||
}
|
||||
}
|
||||
d = mul_add_inp(c, a, a_len, b);
|
||||
if (d) {
|
||||
c += a_len;
|
||||
do {
|
||||
mp_digit sum = d + *c;
|
||||
*c++ = sum;
|
||||
d = sum < d;
|
||||
} while (d);
|
||||
}
|
||||
} else {
|
||||
v8_mpv_mul_d_add_prop(a, a_len, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SOLARIS2_5)
|
||||
static int
|
||||
isSparcV8PlusVis(void)
|
||||
{
|
||||
long buflen;
|
||||
int rv = 0; /* false */
|
||||
char buf[256];
|
||||
buflen = sysinfo(SI_MACHINE, buf, sizeof buf);
|
||||
if (buflen > 0) {
|
||||
rv = (!strcmp(buf, "sun4u") || !strcmp(buf, "sun4u1"));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#else /* SunOS2.6or higher has SI_ISALIST */
|
||||
|
||||
static int
|
||||
isSparcV8PlusVis(void)
|
||||
{
|
||||
long buflen;
|
||||
int rv = 0; /* false */
|
||||
char buf[256];
|
||||
buflen = sysinfo(SI_ISALIST, buf, sizeof buf);
|
||||
if (buflen > 0) {
|
||||
#if defined(MP_USE_LONG_DIGIT)
|
||||
char * found = strstr(buf, "sparcv9+vis");
|
||||
#else
|
||||
char * found = strstr(buf, "sparcv8plus+vis");
|
||||
#endif
|
||||
rv = (found != 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef void MPVmpy(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c);
|
||||
|
||||
/* forward static function declarations */
|
||||
static MPVmpy sp_mpv_mul_d;
|
||||
static MPVmpy sp_mpv_mul_d_add;
|
||||
static MPVmpy sp_mpv_mul_d_add_prop;
|
||||
|
||||
static MPVmpy *p_mpv_mul_d = &sp_mpv_mul_d;
|
||||
static MPVmpy *p_mpv_mul_d_add = &sp_mpv_mul_d_add;
|
||||
static MPVmpy *p_mpv_mul_d_add_prop = &sp_mpv_mul_d_add_prop;
|
||||
|
||||
static void
|
||||
initPtrs(void)
|
||||
{
|
||||
if (isSparcV8PlusVis()) {
|
||||
p_mpv_mul_d = &vis_mpv_mul_d;
|
||||
p_mpv_mul_d_add = &vis_mpv_mul_d_add;
|
||||
p_mpv_mul_d_add_prop = &vis_mpv_mul_d_add_prop;
|
||||
} else {
|
||||
p_mpv_mul_d = &v8_mpv_mul_d;
|
||||
p_mpv_mul_d_add = &v8_mpv_mul_d_add;
|
||||
p_mpv_mul_d_add_prop = &v8_mpv_mul_d_add_prop;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d_add)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
static void
|
||||
sp_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
initPtrs();
|
||||
(* p_mpv_mul_d_add_prop)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
|
||||
/* This is the external interface */
|
||||
|
||||
void
|
||||
s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
void
|
||||
s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d_add)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
void
|
||||
s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
|
||||
{
|
||||
(* p_mpv_mul_d_add_prop)(a, a_len, b, c);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
;
|
||||
; mpi_x86.asm - assembly language implementation of s_mpv_ functions.
|
||||
;
|
||||
; ***** 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 Netscape security libraries.
|
||||
;
|
||||
; 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):
|
||||
;
|
||||
; 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 *****
|
||||
|
||||
; $Id: mpi_x86.asm,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
.386p
|
||||
.MODEL FLAT
|
||||
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
|
||||
_TEXT SEGMENT
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
|
||||
public _s_mpv_mul_d
|
||||
_s_mpv_mul_d PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_2 ; jmp if a_len == 0
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
cld
|
||||
L_1:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_1 ; jmp if a_len != 0
|
||||
L_2:
|
||||
mov [edi],ebx ; *c = carry
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d ENDP
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
public _s_mpv_mul_d_add
|
||||
_s_mpv_mul_d_add PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_4 ; jmp if a_len == 0
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
cld
|
||||
L_3:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_3 ; jmp if a_len != 0
|
||||
L_4:
|
||||
mov [edi],ebx ; *c = carry
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d_add ENDP
|
||||
|
||||
; ebp - 36: caller's esi
|
||||
; ebp - 32: caller's edi
|
||||
; ebp - 28:
|
||||
; ebp - 24:
|
||||
; ebp - 20:
|
||||
; ebp - 16:
|
||||
; ebp - 12:
|
||||
; ebp - 8:
|
||||
; ebp - 4:
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: a argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: b argument
|
||||
; ebp + 20: c argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
public _s_mpv_mul_d_add_prop
|
||||
_s_mpv_mul_d_add_prop PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,28
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; ecx = a_len
|
||||
mov edi,[ebp+20]
|
||||
cmp ecx,0
|
||||
je L_6 ; jmp if a_len == 0
|
||||
cld
|
||||
mov esi,[ebp+8] ; esi = a
|
||||
L_5:
|
||||
lodsd ; eax = [ds:esi]; esi += 4
|
||||
mov edx,[ebp+16] ; edx = b
|
||||
mul edx ; edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add eax,ebx ; add carry (ebx) to edx:eax
|
||||
adc edx,0
|
||||
mov ebx,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
adc edx,0
|
||||
mov ebx,edx ; high half of product becomes next carry
|
||||
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_5 ; jmp if a_len != 0
|
||||
L_6:
|
||||
cmp ebx,0 ; is carry zero?
|
||||
jz L_8
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jnc L_8
|
||||
L_7:
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
adc eax,0
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jc L_7
|
||||
L_8:
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_mul_d_add_prop ENDP
|
||||
|
||||
; ebp - 20: caller's esi
|
||||
; ebp - 16: caller's edi
|
||||
; ebp - 12:
|
||||
; ebp - 8: carry
|
||||
; ebp - 4: a_len local
|
||||
; ebp + 0: caller's ebp
|
||||
; ebp + 4: return address
|
||||
; ebp + 8: pa argument
|
||||
; ebp + 12: a_len argument
|
||||
; ebp + 16: ps argument
|
||||
; ebp + 20:
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
|
||||
public _s_mpv_sqr_add_prop
|
||||
_s_mpv_sqr_add_prop PROC NEAR
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp,12
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
mov ebx,0 ; carry = 0
|
||||
mov ecx,[ebp+12] ; a_len
|
||||
mov edi,[ebp+16] ; edi = ps
|
||||
cmp ecx,0
|
||||
je L_11 ; jump if a_len == 0
|
||||
cld
|
||||
mov esi,[ebp+8] ; esi = pa
|
||||
L_10:
|
||||
lodsd ; eax = [ds:si]; si += 4;
|
||||
mul eax
|
||||
|
||||
add eax,ebx ; add "carry"
|
||||
adc edx,0
|
||||
mov ebx,[edi]
|
||||
add eax,ebx ; add low word from result
|
||||
mov ebx,[edi+4]
|
||||
stosd ; [es:di] = eax; di += 4;
|
||||
adc edx,ebx ; add high word from result
|
||||
mov ebx,0
|
||||
mov eax,edx
|
||||
adc ebx,0
|
||||
stosd ; [es:di] = eax; di += 4;
|
||||
dec ecx ; --a_len
|
||||
jnz L_10 ; jmp if a_len != 0
|
||||
L_11:
|
||||
cmp ebx,0 ; is carry zero?
|
||||
jz L_14
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
add eax,ebx
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jnc L_14
|
||||
L_12:
|
||||
mov eax,[edi] ; add in current word from *c
|
||||
adc eax,0
|
||||
stosd ; [es:edi] = ax; edi += 4;
|
||||
jc L_12
|
||||
L_14:
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
_s_mpv_sqr_add_prop ENDP
|
||||
|
||||
;
|
||||
; Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
; so its high bit is 1. This code is from NSPR.
|
||||
;
|
||||
; mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
; mp_digit *qp, mp_digit *rp)
|
||||
|
||||
; Dump of assembler code for function s_mpv_div_2dx1d:
|
||||
;
|
||||
; esp + 0: Caller's ebx
|
||||
; esp + 4: return address
|
||||
; esp + 8: Nhi argument
|
||||
; esp + 12: Nlo argument
|
||||
; esp + 16: divisor argument
|
||||
; esp + 20: qp argument
|
||||
; esp + 24: rp argument
|
||||
; registers:
|
||||
; eax:
|
||||
; ebx: carry
|
||||
; ecx: a_len
|
||||
; edx:
|
||||
; esi: a ptr
|
||||
; edi: c ptr
|
||||
;
|
||||
public _s_mpv_div_2dx1d
|
||||
_s_mpv_div_2dx1d PROC NEAR
|
||||
push ebx
|
||||
mov edx,[esp+8]
|
||||
mov eax,[esp+12]
|
||||
mov ebx,[esp+16]
|
||||
div ebx
|
||||
mov ebx,[esp+20]
|
||||
mov [ebx],eax
|
||||
mov ebx,[esp+24]
|
||||
mov [ebx],edx
|
||||
xor eax,eax ; return zero
|
||||
pop ebx
|
||||
ret
|
||||
nop
|
||||
_s_mpv_div_2dx1d ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
END
|
||||
@@ -1,345 +0,0 @@
|
||||
#
|
||||
# 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 Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
# $Id: mpi_x86.s,v 1.4 2003-10-24 04:47:23 wchang0222%aol.com Exp $
|
||||
#
|
||||
|
||||
.text
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d
|
||||
.type s_mpv_mul_d,@function
|
||||
s_mpv_mul_d:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 2f # jmp if a_len == 0
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
cld
|
||||
1:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 1b # jmp if a_len != 0
|
||||
2:
|
||||
mov %ebx,0(%edi) # *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d_add
|
||||
.type s_mpv_mul_d_add,@function
|
||||
s_mpv_mul_d_add:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 4f # jmp if a_len == 0
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
cld
|
||||
3:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx # add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 3b # jmp if a_len != 0
|
||||
4:
|
||||
mov %ebx,0(%edi) # *c = carry
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 36: caller's esi
|
||||
# ebp - 32: caller's edi
|
||||
# ebp - 28:
|
||||
# ebp - 24:
|
||||
# ebp - 20:
|
||||
# ebp - 16:
|
||||
# ebp - 12:
|
||||
# ebp - 8:
|
||||
# ebp - 4:
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: a argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: b argument
|
||||
# ebp + 20: c argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
.globl s_mpv_mul_d_add_prop
|
||||
.type s_mpv_mul_d_add_prop,@function
|
||||
s_mpv_mul_d_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $28,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # ecx = a_len
|
||||
mov 20(%ebp),%edi
|
||||
cmp $0,%ecx
|
||||
je 6f # jmp if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi # esi = a
|
||||
5:
|
||||
lodsl # eax = [ds:esi]; esi += 4
|
||||
mov 16(%ebp),%edx # edx = b
|
||||
mull %edx # edx:eax = Phi:Plo = a_i * b
|
||||
|
||||
add %ebx,%eax # add carry (%ebx) to edx:eax
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx # add in current word from *c
|
||||
add %ebx,%eax
|
||||
adc $0,%edx
|
||||
mov %edx,%ebx # high half of product becomes next carry
|
||||
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 5b # jmp if a_len != 0
|
||||
6:
|
||||
cmp $0,%ebx # is carry zero?
|
||||
jz 8f
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jnc 8f
|
||||
7:
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jc 7b
|
||||
8:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
# ebp - 20: caller's esi
|
||||
# ebp - 16: caller's edi
|
||||
# ebp - 12:
|
||||
# ebp - 8: carry
|
||||
# ebp - 4: a_len local
|
||||
# ebp + 0: caller's ebp
|
||||
# ebp + 4: return address
|
||||
# ebp + 8: pa argument
|
||||
# ebp + 12: a_len argument
|
||||
# ebp + 16: ps argument
|
||||
# ebp + 20:
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
|
||||
.globl s_mpv_sqr_add_prop
|
||||
.type s_mpv_sqr_add_prop,@function
|
||||
s_mpv_sqr_add_prop:
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
sub $12,%esp
|
||||
push %edi
|
||||
push %esi
|
||||
push %ebx
|
||||
movl $0,%ebx # carry = 0
|
||||
mov 12(%ebp),%ecx # a_len
|
||||
mov 16(%ebp),%edi # edi = ps
|
||||
cmp $0,%ecx
|
||||
je 11f # jump if a_len == 0
|
||||
cld
|
||||
mov 8(%ebp),%esi # esi = pa
|
||||
10:
|
||||
lodsl # %eax = [ds:si]; si += 4;
|
||||
mull %eax
|
||||
|
||||
add %ebx,%eax # add "carry"
|
||||
adc $0,%edx
|
||||
mov 0(%edi),%ebx
|
||||
add %ebx,%eax # add low word from result
|
||||
mov 4(%edi),%ebx
|
||||
stosl # [es:di] = %eax; di += 4;
|
||||
adc %ebx,%edx # add high word from result
|
||||
movl $0,%ebx
|
||||
mov %edx,%eax
|
||||
adc $0,%ebx
|
||||
stosl # [es:di] = %eax; di += 4;
|
||||
dec %ecx # --a_len
|
||||
jnz 10b # jmp if a_len != 0
|
||||
11:
|
||||
cmp $0,%ebx # is carry zero?
|
||||
jz 14f
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
add %ebx,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jnc 14f
|
||||
12:
|
||||
mov 0(%edi),%eax # add in current word from *c
|
||||
adc $0,%eax
|
||||
stosl # [es:edi] = ax; edi += 4;
|
||||
jc 12b
|
||||
14:
|
||||
pop %ebx
|
||||
pop %esi
|
||||
pop %edi
|
||||
leave
|
||||
ret
|
||||
nop
|
||||
|
||||
#
|
||||
# Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
|
||||
# so its high bit is 1. This code is from NSPR.
|
||||
#
|
||||
# mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
|
||||
# mp_digit *qp, mp_digit *rp)
|
||||
|
||||
# esp + 0: Caller's ebx
|
||||
# esp + 4: return address
|
||||
# esp + 8: Nhi argument
|
||||
# esp + 12: Nlo argument
|
||||
# esp + 16: divisor argument
|
||||
# esp + 20: qp argument
|
||||
# esp + 24: rp argument
|
||||
# registers:
|
||||
# eax:
|
||||
# ebx: carry
|
||||
# ecx: a_len
|
||||
# edx:
|
||||
# esi: a ptr
|
||||
# edi: c ptr
|
||||
#
|
||||
|
||||
.globl s_mpv_div_2dx1d
|
||||
.type s_mpv_div_2dx1d,@function
|
||||
s_mpv_div_2dx1d:
|
||||
push %ebx
|
||||
mov 8(%esp),%edx
|
||||
mov 12(%esp),%eax
|
||||
mov 16(%esp),%ebx
|
||||
div %ebx
|
||||
mov 20(%esp),%ebx
|
||||
mov %eax,0(%ebx)
|
||||
mov 24(%esp),%ebx
|
||||
mov %edx,0(%ebx)
|
||||
xor %eax,%eax # return zero
|
||||
pop %ebx
|
||||
ret
|
||||
nop
|
||||
|
||||
# Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack, "", @progbits
|
||||
.previous
|
||||
@@ -1,465 +0,0 @@
|
||||
/*
|
||||
* mplogic.c
|
||||
*
|
||||
* Bitwise logical operations on MPI values
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* 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 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 ***** */
|
||||
/* $Id: mplogic.c,v 1.15 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#include "mpi-priv.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* {{{ Lookup table for population count */
|
||||
|
||||
static unsigned char bitc[] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_not(a, b) - compute b = ~a
|
||||
mpl_and(a, b, c) - compute c = a & b
|
||||
mpl_or(a, b, c) - compute c = a | b
|
||||
mpl_xor(a, b, c) - compute c = a ^ b
|
||||
*/
|
||||
|
||||
/* {{{ mpl_not(a, b) */
|
||||
|
||||
mp_err mpl_not(mp_int *a, mp_int *b)
|
||||
{
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
/* This relies on the fact that the digit type is unsigned */
|
||||
for(ix = 0; ix < USED(b); ix++)
|
||||
DIGIT(b, ix) = ~DIGIT(b, ix);
|
||||
|
||||
s_mp_clamp(b);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_not() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_and(a, b, c) */
|
||||
|
||||
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) <= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) &= DIGIT(other, ix);
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_and() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_or(a, b, c) */
|
||||
|
||||
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) >= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) |= DIGIT(other, ix);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_or() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_xor(a, b, c) */
|
||||
|
||||
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_int *which, *other;
|
||||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if(USED(a) >= USED(b)) {
|
||||
which = a;
|
||||
other = b;
|
||||
} else {
|
||||
which = b;
|
||||
other = a;
|
||||
}
|
||||
|
||||
if((res = mp_copy(which, c)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
for(ix = 0; ix < USED(which); ix++)
|
||||
DIGIT(c, ix) ^= DIGIT(other, ix);
|
||||
|
||||
s_mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_xor() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_rsh(a, b, d) - b = a >> d
|
||||
mpl_lsh(a, b, d) - b = a << d
|
||||
*/
|
||||
|
||||
/* {{{ mpl_rsh(a, b, d) */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
s_mp_div_2d(b, d);
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_rsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_lsh(a, b, d) */
|
||||
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
|
||||
{
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL, MP_BADARG);
|
||||
|
||||
if((res = mp_copy(a, b)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
return s_mp_mul_2d(b, d);
|
||||
|
||||
} /* end mpl_lsh() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_num_set(a, num)
|
||||
|
||||
Count the number of set bits in the binary representation of a.
|
||||
Returns MP_OKAY and sets 'num' to be the number of such bits, if
|
||||
possible. If num is NULL, the result is thrown away, but it is
|
||||
not considered an error.
|
||||
|
||||
mpl_num_clear() does basically the same thing for clear bits.
|
||||
*/
|
||||
|
||||
/* {{{ mpl_num_set(a, num) */
|
||||
|
||||
mp_err mpl_num_set(mp_int *a, int *num)
|
||||
{
|
||||
unsigned int ix;
|
||||
int db, nset = 0;
|
||||
mp_digit cur;
|
||||
unsigned char reg;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
for(db = 0; db < sizeof(mp_digit); db++) {
|
||||
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
||||
|
||||
nset += bitc[reg];
|
||||
}
|
||||
}
|
||||
|
||||
if(num)
|
||||
*num = nset;
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mpl_num_set() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ mpl_num_clear(a, num) */
|
||||
|
||||
mp_err mpl_num_clear(mp_int *a, int *num)
|
||||
{
|
||||
unsigned int ix;
|
||||
int db, nset = 0;
|
||||
mp_digit cur;
|
||||
unsigned char reg;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
for(db = 0; db < sizeof(mp_digit); db++) {
|
||||
reg = (unsigned char)(cur >> (CHAR_BIT * db));
|
||||
|
||||
nset += bitc[UCHAR_MAX - reg];
|
||||
}
|
||||
}
|
||||
|
||||
if(num)
|
||||
*num = nset;
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
|
||||
} /* end mpl_num_clear() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
mpl_parity(a)
|
||||
|
||||
Determines the bitwise parity of the value given. Returns MP_EVEN
|
||||
if an even number of digits are set, MP_ODD if an odd number are
|
||||
set.
|
||||
*/
|
||||
|
||||
/* {{{ mpl_parity(a) */
|
||||
|
||||
mp_err mpl_parity(mp_int *a)
|
||||
{
|
||||
unsigned int ix;
|
||||
int par = 0;
|
||||
mp_digit cur;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
for(ix = 0; ix < USED(a); ix++) {
|
||||
int shft = (sizeof(mp_digit) * CHAR_BIT) / 2;
|
||||
|
||||
cur = DIGIT(a, ix);
|
||||
|
||||
/* Compute parity for current digit */
|
||||
while(shft != 0) {
|
||||
cur ^= (cur >> shft);
|
||||
shft >>= 1;
|
||||
}
|
||||
cur &= 1;
|
||||
|
||||
/* XOR with running parity so far */
|
||||
par ^= cur;
|
||||
}
|
||||
|
||||
if(par)
|
||||
return MP_ODD;
|
||||
else
|
||||
return MP_EVEN;
|
||||
|
||||
} /* end mpl_parity() */
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
mpl_set_bit
|
||||
|
||||
Returns MP_OKAY or some error code.
|
||||
Grows a if needed to set a bit to 1.
|
||||
*/
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
|
||||
{
|
||||
mp_size ix;
|
||||
mp_err rv;
|
||||
mp_digit mask;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
if (ix + 1 > MP_USED(a)) {
|
||||
rv = s_mp_pad(a, ix + 1);
|
||||
if (rv != MP_OKAY)
|
||||
return rv;
|
||||
}
|
||||
|
||||
bitNum = bitNum % MP_DIGIT_BIT;
|
||||
mask = (mp_digit)1 << bitNum;
|
||||
if (value)
|
||||
MP_DIGIT(a,ix) |= mask;
|
||||
else
|
||||
MP_DIGIT(a,ix) &= ~mask;
|
||||
s_mp_clamp(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bit
|
||||
|
||||
returns 0 or 1 or some (negative) error code.
|
||||
*/
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
|
||||
{
|
||||
mp_size bit, ix;
|
||||
mp_err rv;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = bitNum / MP_DIGIT_BIT;
|
||||
ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
|
||||
|
||||
bit = bitNum % MP_DIGIT_BIT;
|
||||
rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_get_bits
|
||||
- Extracts numBits bits from a, where the least significant extracted bit
|
||||
is bit lsbNum. Returns a negative value if error occurs.
|
||||
- Because sign bit is used to indicate error, maximum number of bits to
|
||||
be returned is the lesser of (a) the number of bits in an mp_digit, or
|
||||
(b) one less than the number of bits in an mp_err.
|
||||
- lsbNum + numbits can be greater than the number of significant bits in
|
||||
integer a, as long as bit lsbNum is in the high order digit of a.
|
||||
*/
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
|
||||
{
|
||||
mp_size rshift = (lsbNum % MP_DIGIT_BIT);
|
||||
mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
|
||||
mp_digit * digit = MP_DIGITS(a) + lsWndx;
|
||||
mp_digit mask = ((1 << numBits) - 1);
|
||||
|
||||
ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
|
||||
ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
|
||||
|
||||
if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
|
||||
(lsWndx + 1 >= MP_USED(a))) {
|
||||
mask &= (digit[0] >> rshift);
|
||||
} else {
|
||||
mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
|
||||
}
|
||||
return (mp_err)mask;
|
||||
}
|
||||
|
||||
/*
|
||||
mpl_significant_bits
|
||||
returns number of significnant bits in abs(a).
|
||||
returns 1 if value is zero.
|
||||
*/
|
||||
mp_err mpl_significant_bits(const mp_int *a)
|
||||
{
|
||||
mp_err bits = 0;
|
||||
int ix;
|
||||
|
||||
ARGCHK(a != NULL, MP_BADARG);
|
||||
|
||||
ix = MP_USED(a);
|
||||
for (ix = MP_USED(a); ix > 0; ) {
|
||||
mp_digit d;
|
||||
d = MP_DIGIT(a, --ix);
|
||||
if (d) {
|
||||
while (d) {
|
||||
++bits;
|
||||
d >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
bits += ix * MP_DIGIT_BIT;
|
||||
if (!bits)
|
||||
bits = 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* HERE THERE BE DRAGONS */
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* mplogic.h
|
||||
*
|
||||
* Bitwise logical operations on MPI values
|
||||
*
|
||||
* ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael J. Fromberger.
|
||||
* 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 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 ***** */
|
||||
/* $Id: mplogic.h,v 1.7 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#ifndef _H_MPLOGIC_
|
||||
#define _H_MPLOGIC_
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
/*
|
||||
The logical operations treat an mp_int as if it were a bit vector,
|
||||
without regard to its sign (an mp_int is represented in a signed
|
||||
magnitude format). Values are treated as if they had an infinite
|
||||
string of zeros left of the most-significant bit.
|
||||
*/
|
||||
|
||||
/* Parity results */
|
||||
|
||||
#define MP_EVEN MP_YES
|
||||
#define MP_ODD MP_NO
|
||||
|
||||
/* Bitwise functions */
|
||||
|
||||
mp_err mpl_not(mp_int *a, mp_int *b); /* one's complement */
|
||||
mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND */
|
||||
mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c); /* bitwise OR */
|
||||
mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR */
|
||||
|
||||
/* Shift functions */
|
||||
|
||||
mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d); /* right shift */
|
||||
mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d); /* left shift */
|
||||
|
||||
/* Bit count and parity */
|
||||
|
||||
mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */
|
||||
mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */
|
||||
mp_err mpl_parity(mp_int *a); /* determine parity */
|
||||
|
||||
/* Get & Set the value of a bit */
|
||||
|
||||
mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value);
|
||||
mp_err mpl_get_bit(const mp_int *a, mp_size bitNum);
|
||||
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits);
|
||||
mp_err mpl_significant_bits(const mp_int *a);
|
||||
|
||||
#endif /* end _H_MPLOGIC_ */
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user